/* $Id$ */
/* 
 * Copyright (C) 2008-2010 Teluu Inc. (http://www.teluu.com)
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 */

/**
 * \page page_httpdemo_c Samples: HTTP Client demo
 *
 * This file is pjsip-apps/src/samples/httpdemo.c
 *
 * \includelineno httpdemo.c
 */

#include <pjlib.h>
#include <pjlib-util.h>
#include <pjlib-util/http_client.h>
#include <pjsip.h>
#include <pjmedia.h>
#include <pjnath.h>
#include <pjsip_simple.h>

static pj_timer_heap_t *timer_heap;
static pj_ioqueue_t *ioqueue;
static pj_pool_t *pool;
static pj_http_req *http_req;
static pj_pool_factory *mem;
static FILE *f = NULL;

//#define VERBOSE
#define THIS_FILE	    "http_demo"

static void on_response(pj_http_req *http_req, const pj_http_resp *resp)
{
    unsigned i;

    PJ_UNUSED_ARG(http_req);
    PJ_LOG(3,(THIS_FILE, "%.*s %d %.*s", (int)resp->version.slen, resp->version.ptr,
				           resp->status_code,
				           (int)resp->reason.slen, resp->reason.ptr));

    for (i=0; i<resp->headers.count; ++i) {
	const pj_http_header_elmt *h = &resp->headers.header[i];

	if (!pj_stricmp2(&h->name, "Content-Length") ||
	    !pj_stricmp2(&h->name, "Content-Type"))
	{
	    PJ_LOG(3,(THIS_FILE, "%.*s: %.*s",
		      (int)h->name.slen, h->name.ptr,
		      (int)h->value.slen, h->value.ptr));
	}
    }
}

static void on_send_data(pj_http_req *http_req, void **data, pj_size_t *size)
{
	PJ_UNUSED_ARG(http_req);
	PJ_UNUSED_ARG(size);
	PJ_UNUSED_ARG(data);
}

static void on_data_read(pj_http_req *hreq, void *data, pj_size_t size)
{
    PJ_UNUSED_ARG(hreq);

    if (size > 0) {
        fwrite(data, 1, size, f);
        fflush(f);
#ifdef VERBOSE
        PJ_LOG(3, (THIS_FILE, "Data received: %d bytes", size));
        printf("%.*s\n", (int)size, (char *)data);
#endif
    }
}

static void on_complete(pj_http_req *hreq, pj_status_t status,
                        const pj_http_resp *resp)
{
    PJ_UNUSED_ARG(hreq);

    if (status != PJ_SUCCESS) {
        PJ_PERROR(1, (THIS_FILE, status, "HTTP request completed with error"));
        return;
    }
    PJ_LOG(3, (THIS_FILE, "Data completed: %d bytes", resp->size));
    if (resp->size > 0 && resp->data) {
#ifdef VERBOSE
        printf("%.*s\n", (int)resp->size, (char *)resp->data);
#endif
    }
}

pj_status_t getURL(const char *curl)
{
    pj_str_t url;
    pj_http_req_callback hcb;
    pj_status_t status;

    pj_bzero(&hcb, sizeof(hcb));
    hcb.on_complete = &on_complete;
    hcb.on_data_read = &on_data_read;
    hcb.on_send_data = &on_send_data;
    hcb.on_response = &on_response;

    /* Create pool, timer, and ioqueue */
    pool = pj_pool_create(mem, NULL, 8192, 4096, NULL);
    if (pj_timer_heap_create(pool, 16, &timer_heap))
        return -31;
    if (pj_ioqueue_create(pool, 16, &ioqueue))
        return -32;

    pj_strdup2(pool, &url, curl);

    if ((status = pj_http_req_create(pool, &url, timer_heap, ioqueue, 
                           NULL, &hcb, &http_req)) != PJ_SUCCESS)
        return status;

    if ((status = pj_http_req_start(http_req)) != PJ_SUCCESS)
        return status;

    while (pj_http_req_is_running(http_req)) {
        pj_time_val delay = {0, 50};
	pj_ioqueue_poll(ioqueue, &delay);
	pj_timer_heap_poll(timer_heap, NULL);
    }

    pj_http_req_destroy(http_req);
    pj_ioqueue_destroy(ioqueue);
    pj_timer_heap_destroy(timer_heap);
    pj_pool_release(pool);

    return PJ_SUCCESS;
}
/*
 * main()
 */
int main(int argc, char *argv[])
{
    pj_caching_pool cp;
    pj_status_t status;

    if (argc < 2 || argc > 3) {
	puts("Usage: httpdemo URL [output-filename]");
	return 1;
    }

    pj_log_set_level(5);

    pj_init();
    pj_caching_pool_init(&cp, NULL, 0);
    mem = &cp.factory;
    pjlib_util_init();

    if (argc > 2)
	f = fopen(argv[2], "wb");
    else
	f = stdout;

    status = getURL(argv[1]);
    if (status != PJ_SUCCESS) {
        PJ_PERROR(1, (THIS_FILE, status, "Error"));
    }

    if (f != stdout)
	fclose(f);

    pj_caching_pool_destroy(&cp);
    pj_shutdown();
    return 0;
}
