/*
 * 	wmSun-1.12 (C) 2014 Cezary M. Kruk <c.kruk@bigfoot.com>
 * 	wmSun-1.03 (C) 1999 Mike Henderson <mghenderson@lanl.gov>
 *
 * 	Shows Sun Rise/Sun Set Times...
 *
 * 	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 3 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, see <http://www.gnu.org/licenses/>.
 *
 */

/*
 *   Includes
 */
#include <stdio.h>
#include <math.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <X11/X.h>
#include <X11/xpm.h>
#include "../wmgeneral/wmgeneral.h"
#include "wmSun_aa1.xpm"
#include "wmSun_aa2.xpm"
#include "wmSun.xpm"

/*
 *  Delay between refreshes (in microseconds)
 */
#define DELAY 125000L
#define WMSUN_VERSION "1.12"

#define DegPerRad       57.29577951308232087680
#define RadPerDeg        0.01745329251994329576

char	wmSun_mask_bits[64*64];
int	wmSun_mask_width = 64;
int	wmSun_mask_height = 64;

XpmColorSymbol colors[1] = {{NULL, NULL, 0}};

void ParseCMDLine(int argc, char *argv[]);
void pressEvent(XButtonEvent *xev);

int	UseUserTimeDiff = 0;
int	UseUserDate = 0;
long	UserDate;
double 	Glat, Glon, SinGlat, CosGlat, TimeZone, UserTimeDiff;

int	SunType = 10;
int	AntiAlias = 0;
int	xDigit[11] = {8, 17, 26, 35, 44, 53, 62, 71, 80, 89, 98};

int 	OpenWindow = 1;

/*
 *   Main
 */
int main(int argc, char *argv[]) {

    struct tm		*GMTTime, *LocalTime;
    XEvent		event;
    int			i, k, j, ImageNumber;
    int 		Year, Month, DayOfWeek;
    int			LocalDayOfMonth, DayOfMonth;
    int			Hours, Mins, Secs, OldSecs, digit, xoff, xsize;
    int			OldMins;
    long		CurrentLocalTime, CurrentGMTTime, date;
    double		UT, val, RA, DEC, LTRise, LTSet, LocalHour, hour24();
    int			D, H, M, S, sgn, A, B, q;
    char		str[10];

    /*
     *  Parse any command line arguments.
     */
    Glat = Glon = 0.0;
    ParseCMDLine(argc, argv);
    Glat *= RadPerDeg; SinGlat = sin( Glat ); CosGlat = cos( Glat );

    /*
     *  Loop until we die
     */
    OldMins = -999;

    while(1) {

            CurrentGMTTime = time(CurrentTime); GMTTime = gmtime(&CurrentGMTTime); 
	    DayOfMonth = GMTTime->tm_mday;

	    UT = GMTTime->tm_hour + GMTTime->tm_min/60.0 + GMTTime->tm_sec/3600.0;
	    Year = GMTTime->tm_year+1900;
	    Month = GMTTime->tm_mon+1;

	    CurrentLocalTime = CurrentGMTTime; LocalTime = localtime(&CurrentLocalTime);
	    LocalDayOfMonth = LocalTime->tm_mday;
	    Mins = LocalTime->tm_min;

	    LocalHour = LocalTime->tm_hour + LocalTime->tm_min/60.0 + LocalTime->tm_sec/3600.0;

	    if (OldMins != Mins) {

		if (UseUserDate){
	    	    date =  UserDate;
		    Year = date/10000;
		    date -= Year*10000;
		    Month = date/100;
		    date -= Month*100;
		    DayOfMonth = date;
		    date = UserDate;
		} else {
	    	    date = Year*10000 + Month*100 + DayOfMonth;
		}
	    	TimeZone = (UseUserTimeDiff) ? UserTimeDiff : UT - LocalHour;

   	    	/*
	    	 *  Compute Sun Rise/Set Times in Local Time
	    	 */
	    	SunRise(Year, Month, DayOfMonth, LocalHour, &LTRise, &LTSet);

		if ((LocalHour >= LTRise) && (LocalHour <= LTSet)) {
			SunType = 1;
		} else {
			SunType = 0;
		}

		if (OpenWindow == 1) {
			if (AntiAlias == 2) {
				createXBMfromXPM(wmSun_mask_bits, wmSun_aa2_xpm, wmSun_mask_width, wmSun_mask_height);
				openXwindow(argc, argv, wmSun_aa2_xpm, wmSun_mask_bits, wmSun_mask_width, wmSun_mask_height, colors);
			} else
			if (AntiAlias == 1) {
				createXBMfromXPM(wmSun_mask_bits, wmSun_aa1_xpm, wmSun_mask_width, wmSun_mask_height);
				openXwindow(argc, argv, wmSun_aa1_xpm, wmSun_mask_bits, wmSun_mask_width, wmSun_mask_height, colors);
			} else {
				createXBMfromXPM(wmSun_mask_bits, wmSun_xpm, wmSun_mask_width, wmSun_mask_height);
				openXwindow(argc, argv, wmSun_xpm, wmSun_mask_bits, wmSun_mask_width, wmSun_mask_height, colors);
			}
		AddMouseRegion(0, 5, 5, 58, 58);
		OpenWindow = 0;
		}

	    if (SunType == 0) {

		/*
		 *  Clear Plotting area
		 */
		copyXPMArea(5, 69, 54, 54, 5, 5);

		// 1=xpmwidth, 2=xpmheight, 3=charwidth, 4=charheight, 5=posx 6=posy
		if (LTRise > 0.0) {
	    	    val = LTRise;
	    	    H = (int)val; val = (val-H)*60.0;
	    	    M = (int)val;
	    	    copyXPMArea(xDigit[H/10], 137, 7, 9, 15, 17);
	    	    copyXPMArea(xDigit[H%10], 137, 7, 9, 23, 17);
	    	    copyXPMArea(xDigit[10],   139, 3, 7, 30, 18);
	    	    copyXPMArea(xDigit[M/10], 137, 7, 9, 34, 17);
	    	    copyXPMArea(xDigit[M%10], 137, 7, 9, 42, 17);
		} else {
	    	    copyXPMArea(102, 141, 6, 1, 15, 20);
	    	    copyXPMArea(102, 141, 6, 1, 23, 20);
	    	    copyXPMArea(98, 139, 3, 7, 30, 18);
	    	    copyXPMArea(102, 141, 6, 1, 34, 20);
	    	    copyXPMArea(102, 141, 6, 1, 42, 20);
		}

		if (LTSet > 0.0) {
	    	    val = LTSet;
	    	    H = (int)val; val = (val-H)*60.0;
	    	    M = (int)val;
	    	    copyXPMArea(xDigit[H/10], 137, 7, 9, 15, 38);
	    	    copyXPMArea(xDigit[H%10], 137, 7, 9, 23, 38);
	    	    copyXPMArea(xDigit[10],   139, 3, 7, 30, 39);
	    	    copyXPMArea(xDigit[M/10], 137, 7, 9, 34, 38);
	    	    copyXPMArea(xDigit[M%10], 137, 7, 9, 42, 38);
		} else {
	    	    copyXPMArea(102, 141, 6, 1, 15, 41);
	    	    copyXPMArea(102, 141, 6, 1, 23, 41);
	    	    copyXPMArea(98, 139, 3, 7, 30, 39);
	    	    copyXPMArea(102, 141, 6, 1, 34, 41);
	    	    copyXPMArea(102, 141, 6, 1, 42, 41);
		}
	    } else if (SunType == 1) {

	    	/*
	    	 *  Clear Plotting area
	    	 */
	    	copyXPMArea(69, 69, 54, 54, 5, 5);

		// 1=xpmwidth, 2=xpmheight, 3=charwidth, 4=charheight, 5=posx 6=posy
		if (LTRise > 0.0) {
	    	    val = LTRise;
	    	    H = (int)val; val = (val-H)*60.0;
	    	    M = (int)val;
	    	    copyXPMArea(xDigit[H/10], 167, 7, 9, 15, 17);
	    	    copyXPMArea(xDigit[H%10], 167, 7, 9, 23, 17);
	    	    copyXPMArea(xDigit[10],   169, 3, 7, 30, 18);
	    	    copyXPMArea(xDigit[M/10], 167, 7, 9, 34, 17);
	    	    copyXPMArea(xDigit[M%10], 167, 7, 9, 42, 17);
		} else {
	    	    copyXPMArea(102, 171, 6, 1, 15, 20);
	    	    copyXPMArea(102, 171, 6, 1, 23, 20);
	    	    copyXPMArea(98, 169, 3, 7, 30, 18);
	    	    copyXPMArea(102, 171, 6, 1, 34, 20);
	    	    copyXPMArea(102, 171, 6, 1, 42, 20);
		}

		if (LTSet > 0.0) {
	    	    val = LTSet;
	    	    H = (int)val; val = (val-H)*60.0;
	    	    M = (int)val;
	    	    copyXPMArea(xDigit[H/10], 167, 7, 9, 15, 38);
	    	    copyXPMArea(xDigit[H%10], 167, 7, 9, 23, 38);
	    	    copyXPMArea(xDigit[10],   169, 3, 7, 30, 39);
	    	    copyXPMArea(xDigit[M/10], 167, 7, 9, 34, 38);
	    	    copyXPMArea(xDigit[M%10], 167, 7, 9, 42, 38);
		} else {
	    	    copyXPMArea(102, 171, 6, 1, 15, 41);
	    	    copyXPMArea(102, 171, 6, 1, 23, 41);
	    	    copyXPMArea(98, 169, 3, 7, 30, 39);
	    	    copyXPMArea(102, 171, 6, 1, 34, 41);
	    	    copyXPMArea(102, 171, 6, 1, 42, 41);
		}
	    }

	    OldMins = Mins;

	    }


	/*
	 *   Process any pending X events
	 */
        while(XPending(display)){
            XNextEvent(display, &event);
            switch(event.type){
                case Expose:
                        RedrawWindow();
                        break;
                case ButtonPress:
                        pressEvent(&event.xbutton);
                        break;
                case ButtonRelease:
                        break;
            }
        }

	
	/*
	 *  Redraw and wait for next update 
	 */
	RedrawWindow();
	usleep(DELAY);

        }

     }

/*
 *   ParseCMDLine()
 */
void ParseCMDLine(int argc, char *argv[]) {

    int  i;

    for (i = 1; i < argc; i++) {

        if (!strcmp(argv[i], "-display")){

	    ++i;

        } else if (!strcmp(argv[i], "-lat")){

	    Glat = atof(argv[++i]);

        } else if (!strcmp(argv[i], "-lon")){

	    Glon = atof(argv[++i]);

        } else if (!strcmp(argv[i], "-td")){

	    UseUserTimeDiff = 1;
	    UserTimeDiff = atof(argv[++i]);

        } else if (!strcmp(argv[i], "-date")){

	    UseUserDate = 1;
	    UserDate = atoi(argv[++i]);
	
	} else if (!strcmp(argv[i], "-aa")) {

	    AntiAlias = atof(argv[++i]);

	} else {
	    printf("\nwmSun version: %s\n", WMSUN_VERSION);
	    printf("\nusage: wmSun [-lat <latitude>] [-lon <longitude>]\n\n");
	    printf("  -display <display>  : use alternate X display.\n");
	    printf("  -lat <latitude>     : observers latitude -- positive to the north.\n");
	    printf("  -lon <longitude>    : observers longitude -- positiwe to the west.\n");
	    printf("  -td <UT - LT>       : user-defined difference between UT an LT (in hours).\n");
	    printf("  -date <yyyymmdd>    : set the date to calculate the sunrise/sunset.\n");
	    printf("  -aa <anti-aliasing> : 0 for none, 1 for font, 2 for font and background\n");
	    printf("                        (default is none).\n");
	    printf("  -h                  : display help screen.\n\n");
	    exit(1);
	}
    }
}

/*
 *  This routine handles button presses. Clicking in the window
 *  toggles the display.
 *
 */
void pressEvent(XButtonEvent *xev){

   return;
}

