/***************************** LICENSE START ***********************************

 Copyright 2012 ECMWF and INPE. This software is distributed under the terms
 of the Apache License version 2.0. In applying this license, ECMWF does not
 waive the privileges and immunities granted to it by virtue of its status as
 an Intergovernmental Organization or submit itself to any jurisdiction.

 ***************************** LICENSE END *************************************/

#include <X11/Xatom.h>
#include <X11/Intrinsic.h>
#include <X11/Shell.h>

#include <Xm/Xm.h>
#include <Xm/DialogS.h>
#include <Xm/Scale.h>
#include <Xm/Label.h>
#include <Xm/RowColumn.h>
#include <Xm/Frame.h>

#include <mars.h>
#include <progress.h>

static Widget progress_top = (Widget) NULL;
static Widget progress_row = (Widget) NULL;
static Widget progress_box = (Widget) NULL;
static Widget progress_pix = (Widget) NULL;
static Widget progress_scale = (Widget) NULL;
static Widget progress_text = (Widget) NULL;

static Boolean visible;
static long   start;

typedef struct  {
	float  max;
	float  value;
	char   *title;
} info;

static info infos[10];


static int  depth   = 0;
static int  current = 0;


void progress_init(Widget parent)
{
	Arg al[64];      
	int ac = 0;

	if(progress_top) return;

	while(!XtIsShell(parent)) parent = XtParent(parent);


	XtSetArg(al[ac], XmNallowShellResize, TRUE); ac++;
	progress_top = XmCreateDialogShell ( parent, "Metview progress", al, ac );
	ac = 0;
	XtSetArg(al[ac], XmNentryAlignment, XmALIGNMENT_CENTER); ac++;
	progress_row = XmCreateRowColumn ( progress_top, "progress_row", al, ac );
	ac = 0;
	XtSetArg(al[ac], XmNshadowType, (time(0)%2 == 0)?XmSHADOW_OUT:XmSHADOW_IN); ac++;
	progress_box = XmCreateFrame ( progress_row, "progress_box", al, ac );
	ac = 0;
	XtSetArg(al[ac], XmNlabelType, XmPIXMAP); ac++;
	progress_pix = XmCreateLabel ( progress_box, "progress_pix", al, ac );
	ac = 0;
	XtSetValues ( progress_pix,al, ac );
	ac = 0;
	XtSetArg(al[ac], XmNwidth, 400); ac++;
	XtSetArg(al[ac], XmNshowValue, TRUE); ac++;
	XtSetArg(al[ac], XmNminimum, 0); ac++;
	XtSetArg(al[ac], XmNmaximum, 100); ac++;
	XtSetArg(al[ac], XmNorientation, XmHORIZONTAL); ac++;
	XtSetArg(al[ac], XmNprocessingDirection, XmMAX_ON_RIGHT); ac++;
	progress_scale = XmCreateScale ( progress_row, "progress_scale", al, ac );
	ac = 0;
	XtSetArg(al[ac], XmNwidth, 400); ac++;
	XtSetArg(al[ac], XmNrecomputeSize, FALSE); ac++;
	progress_text = XmCreateLabel ( progress_row, "progress_text", al, ac );
	ac = 0;
	XtManageChild(progress_pix);

	ac = 0;
	XtManageChild(progress_scale);
	XtManageChild(progress_text);
	ac = 0;
	visible = False;
}

void progress_pixmap(Pixmap pixmap)
{
	if(pixmap ==0 || pixmap == XmUNSPECIFIED_PIXMAP)
		XtUnmanageChild(progress_box);
	else
	{
		Arg al[64];      
		int ac = 0;
		XtSetArg(al[ac],XmNlabelPixmap,pixmap);ac++;
		XtSetValues(progress_pix,al,ac);
		XtManageChild(progress_box);
	}
}

static void set_title(char *p)
{
	Arg al[64];      
	int ac = 0;

	XmString s = XmStringCreateSimple(p);

	ac = 0;
	XtSetArg(al[ac],XmNlabelString,s);ac++;
	XtSetValues(progress_text,al,ac);
	XmStringFree(s);
}

void progress_start(const char *title,int m)
{
	if(m<=0) m = 1;

	if(title == NULL)
	{
		if(depth == 0) title = "Working..";
		else title = infos[depth-1].title;
	}

	if(depth == 0) {
		start = time(0);
		current = 0;
	}
	
	infos[depth].max   = m;
	infos[depth].value = 0;
	infos[depth].title = strcache(title);

	set_title(infos[depth].title);

	depth++;

	progress_value(0);
}


void progress_value(int v)
{
	float x = 0.0;
	float y = 1.0;
	int   i;

	if(v > infos[depth-1].max) v = infos[depth-1].max;
	infos[depth-1].value = v;

	for(i=0;i<depth;i++)
	{
		x += infos[i].value / infos[i].max * y;
		y = 1.0 / infos[i].max;
	}

	v = (int)(100.0 * x);
	if(v>100) v = 100;

	/* if(v>current)  */
		current = v;

	if(visible)
	{
		XmScaleSetValue(progress_scale,current);		
		XmUpdateDisplay(progress_scale);
	}
	else
	{
		long now = time(0);
		if(now - start >  5 && current < 50) /* 50 % made in 5 sec. */
		{
			visible = TRUE;
			XtRealizeWidget(progress_top);
			XmScaleSetValue(progress_scale,current);
			XtManageChild(progress_row);
			XmUpdateDisplay(progress_scale);
		}
	}
}

void progress_stop(void)
{
	--depth;

	strfree(infos[depth].title);

	if(depth == 0)
	{
		XtUnmanageChild(progress_row);
		visible = False;
		XmUpdateDisplay(progress_scale);
	}
}
