...

// Global variables --

var athFullTimes =  new Array(7), iqFullTimes = new Array(7);
var millisTillIq = new Array(7), millisTillAth = new Array(7);
var minDx;
var ddfs = -1, ats = [], dremain, ciq = [], loctn, CLCLT = 0;
var sliderTicker, nextTicker;
var Lng, Lat, Elev, timeZone, julianDate;
var fajrAng, ishaAng, ishaTime, asrFactor;
var ServerDay;


function getPageParms() {
    "use strict";
    // Set page-specific parameters here

    // Get location
    loctn = document.getElementById("dateBox").innerHTML;
    Lat = Number(document.getElementById("parms").innerHTML.split(',')[0]);
    Lng = Number(document.getElementById("parms").innerHTML.split(',')[1]);
    Elev = Number(document.getElementById("parms").innerHTML.split(',')[2]);
    fajrAng = Number(document.getElementById("parms").innerHTML.split(',')[3]);
    ishaAng = Number(document.getElementById("parms").innerHTML.split(',')[4]);
    ishaTime = Number(document.getElementById("parms").innerHTML.split(',')[5]);
    asrFactor = Number(document.getElementById("parms").innerHTML.split(',')[6]);
    CLCLT = Number(document.getElementById("parms").innerHTML.split(',')[7]);
    ServerDay = Number(document.getElementById("parms").innerHTML.split(',')[8]); // included 10/10/2019

    document.getElementById("parms").innerHTML = "";

//    if(Lat != "" && Lng != "") { CLCLT = true; ddfs = 0; }
//    if(CLCLT === 1) { CLCLT = 1; ddfs = 0; } else CLCLT = 0;
    if(CLCLT === 1) ddfs = 0;

//    var today = new Date();
//    julianDate = jd(today.getFullYear(), today.getMonth()+1, today.getDate());
//    // goes from the westernmost -12:00 to the easternmost +14:00
//    // javascript defines timezone as the difference b/n UTC and local
//    // time. Offset is positive if local time is behind UTC. For prayer
//    // time calculations, we need to invert that, ie, local - UTC.
//    timeZone = -today.getTimezoneOffset()/60;

}

function set12Hrs(h) {
    "use strict";
    h = ((h + 11) % 12 + 1);
    return h;
}

function checkZero(i) {
    "use strict";
    if (i < 10) { i = "0" + i; }
    return i;
}

// To be called at 12:00 midnight
function setNewDate() {
    "use strict";
    var days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], mos = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',  'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], today = new Date(), day = days[today.getDay()], mo = mos[today.getMonth()], dateElement;

    dateElement = document.getElementById("dateBox");
    dateElement.innerHTML = day + "  " + mo + "  " + today.getDate() + "<br>" + loctn;

    julianDate = jd(today.getFullYear(), today.getMonth()+1, today.getDate());
    // goes from the westernmost -12:00 to the easternmost +14:00
    // javascript defines timezone as the difference b/n UTC and local
    // time. Offset is positive if local time is behind UTC. For prayer
    // time calculations, we need to invert that, ie, local - UTC.
    timeZone = -today.getTimezoneOffset()/60;
}

// Prayer Time Calculations Functions:

function fix(a, b) {
    a = a - b * Math.floor(a/b);
    return (a < 0) ? a+b : a;
}

// Degrees to Radians
function dtr(x) {
  return x*Math.PI/180;
}

function rtd(x){
  return x*180/Math.PI;
}

function Sin(x) { return Math.sin(dtr(x)); }
function Asin(x) { return rtd(Math.asin(x)); }
function Cos(x) { return Math.cos(dtr(x)); }
function Acos(x) { return rtd(Math.acos(x)); }
function Atan2(x, y) { return rtd(Math.atan2(x, y)); }
function Acot(x) { return rtd(Math.atan(1/x)); }
function Tan(x) { return Math.tan(dtr(x)); }



// Get julian day
function jd(year, month, day) {
    if (month <= 2) {
        year -= 1;
        month += 12;
    }
    var A = Math.floor(year/ 100);
    var B = 2- A+ Math.floor(A/ 4);

    var JD = Math.floor(365.25* (year+ 4716))+ Math.floor(30.6001* (month+ 1))+ day+ B- 1524.5;
    return JD;
}

function sunAng(jd) {
    var D = jd - 2451545.0;
    var g = fix((357.529 + 0.98560028 * D), 360)
    var q = fix((280.459 + 0.98564736 * D), 360)
    var L = fix((q + 1.915 * Sin(g) + 0.020 * Sin(2 * g)), 360)
    var e = 23.439 - 0.00000036 * D

    var RA = Atan2((Cos(e) * Sin(L)), Cos(L)) / 15;
    var d = Asin((Sin(e) * Sin(L)))  // declination of the Sun
    var EqT = q/15 - fix(RA, 24);    // equation of time
    return {EqT: EqT, decl: d};
}
// Mid-day
function zenith(approxtime) {
    var noon = fix((12 - sunAng(julianDate + approxtime/24).EqT), 24);
    return noon;
}


// To be called at 12:00 midnight and at first load
function getPrayerTimes() {
    "use strict";
    var i, iqIds = ['fajIq', 'dummy', 'dhuIq', 'asrIq', 'magIq', 'ishIq'], athIds = ['fajAth', 'sunAth', 'dhuAth', 'asrAth', 'magAth', 'ishAth'], iqHrs = new Array(6), iqMns = new Array(6), athHrs = new Array(6), athMns = new Array(6), x, a;

    // Read Athan and Iqama times from the DOM
    // Those were inserted by PHP at first load or JS after 24 hrs --
    for (i = 0; i < 6; i += 1) {
        a = document.getElementById(athIds[i]).innerHTML;
        x = a.split(' ')[0];

        athHrs[i] = parseInt(x.split(':')[0], 10); // radix = 10, default!
        if (a.search("PM") > -1 && athHrs[i] < 12) { athHrs[i] += 12; }
        athMns[i] = parseInt(x.split(':')[1], 10);

        if (i !== 1) {
            a = document.getElementById(iqIds[i]).innerHTML;
            x = a.split(' ')[0];
            iqHrs[i] = parseInt(x.split(':')[0], 10);
            if (a.search("PM") > -1 && iqHrs[i] < 12) { iqHrs[i] += 12; }
            iqMns[i] = parseInt(x.split(':')[1], 10);

        } else { iqHrs[1] = athHrs[1]; iqMns[1] = athMns[1]; }
    }

    for (i = 0; i < 6; i += 1) {
        athFullTimes[i] = new Date();
        athFullTimes[i].setHours(athHrs[i], athMns[i], 0, 0);

        iqFullTimes[i] = new Date();
        iqFullTimes[i].setHours(iqHrs[i], iqMns[i], 0, 0);
    }

    // Set pseudo athan and iqama at midnight
    athFullTimes[6] = new Date();
    athFullTimes[6].setDate(athFullTimes[6].getDate() + 1);
    athFullTimes[6].setHours(0, 0, 0, 0);

    iqFullTimes[6] = new Date();
    iqFullTimes[6].setDate(iqFullTimes[6].getDate() + 1);
    iqFullTimes[6].setHours(0, 0, 0, 0);

    /*document.getElementById("debug").innerHTML = "iqHrs[0] = " + iqHrs[0] + "<br>iqHrs[1] = " + iqHrs[1] + "<br>iqHrs[2] = " + iqHrs[2] + "<br>iqHrs[3] = " + iqHrs[3] + "<br>iqHrs[4] = " + iqHrs[4] + "<br>iqHrs[5] = " + iqHrs[5];*/

    // Check for correctness of iqama as always > athan except for Friday.
    for (i = 0; i < 6; i += 1) {
      if(i == 1) continue;
      if(athFullTimes[i].getTime() > iqFullTimes[i].getTime())
        document.getElementById(iqIds[i]).setAttribute("class", "lateIq");
      else document.getElementById(iqIds[i]).setAttribute("class", "");
    }
    //document.getElementById("debug").innerHTML = "To athan: " + getTimeTo(athFullTimes[5])/3600 + "<br>To Iqama: " + getTimeTo(iqFullTimes[5])/3600 + "</br>";
}

// Future athan times
function getFAT() {
    "use strict";
    var ihtml = (document.getElementById("fat").innerHTML).split(';'),
        i,
        x;

    CLCLT = Number(ihtml[0]);  // added Oct 21, 2019
    dremain = Number(ihtml[1]); // chnaged from Number(ihtml[0]) on Oct 21, 2019
    //document.getElementById("debug").innerHTML = "CLCLT = " + CLCLT + " dremain = " + dremain + "</br>";

    // the following is the only way the display gets php CLCLT value
    // note that CLCLT never permanently changes on server! Even when dremain
    // counts down to 0. This may result in conflicting times b/n devices at yearend
    if(CLCLT === 1) {
      ddfs = 0;
      ciq = (ihtml[2]).split(',');
    }
    else {
      //document.getElementById("debug").innerHTML = "CLCLT = " + CLCLT + " dremain = " + dremain + "</br>";
      //if(dremain == 0) dremain +=1; // on Dec 31, next day prayer times (Jan 01) are also sent here, count forward by 1
      //for (i = 0; i < dremain; i += 1) {
      for (i = 0; i <= dremain+1; i += 1) {
          x = (ihtml[i + 2]).split(',');
          ats[i] = [x[1], x[2], x[3], x[4], x[5], x[6]];
      }
      ciq = (ihtml[dremain + 4]).split(',');
    }
    document.getElementById("fat").innerHTML = "";
}

function update_iq(hma, im) {
    "use strict";
    var x, a, h, m, d = new Date();

    x = hma.split(" ")[0];

    h = parseInt(x.split(":")[0], 10);
    if (hma.search("PM") > -1 && h < 12) { h += 12; }
    m = parseInt(x.split(":")[1], 10);

    d.setHours(h, (m + parseInt(im, 10)), 0, 0);

    a = "PM";
    h = d.getHours();
    if (h < 12) { a = "AM"; }
    h = set12Hrs(h);
    m = checkZero(d.getMinutes());

    return (h + ":" + m + " " + a);
}

// reformate decimal time to string time
// rnd: floor, round, ceil
// adj: adjustment in minutes or parts of minutes
function boardTime(time, rnd_type, adj) {
    var mins, hrs, a;

    time = time + adj/60
    hrs = Math.floor(time);

    switch(rnd_type) {
        case 'ceil': mins = Math.ceil((time - hrs)*60); break;
        case 'round': mins = Math.round((time - hrs)*60); break;
        case 'floor': mins = Math.floor((time - hrs)*60); break;
        default: mins = Math.round((time - hrs)*60); break;
    }

    if(mins == 60) { mins = 0; hrs++; }
    if(hrs >= 12) a = "PM"; else a = "AM";

    return set12Hrs(hrs) + ":" + checkZero(mins) + " " + a;

}

function Talpha(angle, d) {
    return Acos((-Sin(angle) - Sin(d) * Sin(Lat))/(Cos(d) * Cos(Lat)))/15;
}

function timeAtSunAng(time, angle, isup) {
    var talpha = Talpha(angle, sunAng(julianDate + time/24).decl);
    if(isup == 'up') talpha = -talpha;
    return zenith(time) + talpha;
}

// Calculate time of Asr athan
function asrTime(time) {
    var decl = sunAng(julianDate + time/24).decl;
    var angle = -Acot(asrFactor + Tan(Math.abs(Lat - decl)));
    return timeAtSunAng(time, angle);
}

// calculate prayer times of today and place in ats[0]
// with CLCLT, ddfs = 0
function calculateAthTimes() {
    var i, times = [5.00, 7.00, 12.00, 15.00, 17.00, 19.00];

    for(i=0; i<3; i++) {

        // Dhuhr
        times[2] = zenith(times[2]) + timeZone - Lng/15;

        // Sunrise/set
        var angle = 0.833 + 0.0347*Math.sqrt(Elev);
        times[1] = timeAtSunAng(times[1], angle, 'up') + timeZone - Lng/15;
        times[4] = timeAtSunAng(times[4], angle) + timeZone - Lng/15;

        // Fajr
        times[0] = timeAtSunAng(times[0], fajrAng, 'up') + timeZone - Lng/15;

        // Isha
        if(ishaAng > 0) times[5] = timeAtSunAng(times[5], ishaAng) + timeZone - Lng/15;
        if(ishaTime > 0) times[5] = times[4] + ishaTime/60;

        // Asr
        times[3] = asrTime(times[3]) + timeZone - Lng/15;

    } // for loop

    ats[ddfs] = times;
    ats[ddfs][0] = boardTime(times[0], 'floor', 0);
    ats[ddfs][1] = boardTime(times[1], 'floor', 0);
    ats[ddfs][2] = boardTime(times[2], 'ceil', 0);
    ats[ddfs][3] = boardTime(times[3], 'ceil', 0);
    ats[ddfs][4] = boardTime(times[4], 'ceil', 0);
    ats[ddfs][5] = boardTime(times[5], 'ceil', 0);
}

// Set athan and iqama times
function setAT() {
    "use strict";
    var i, j, athIds = ['fajAth', 'sunAth', 'dhuAth', 'asrAth', 'magAth', 'ishAth'], iqIds = ['fajIq', 'dhuIq', 'asrIq', 'magIq', 'ishIq'];

    // in case you run out of uploaded data - in case of no reload for a long time
    if(dremain == 0) { CLCLT = 1; ddfs = 0; }

    // Calculate prayer times of today
    if(CLCLT === 1) calculateAthTimes();

    // Set athan and iqama times in table
    for (i = 0; i < 6; i += 1) {
        document.getElementById(athIds[i]).innerHTML = ats[ddfs][i];

        if (i != 1) {
            if (i > 1) { j = i - 1; } else { j = i; }
            if (parseInt(ciq[j], 10) > 0) {
                document.getElementById(iqIds[j]).innerHTML = update_iq(ats[ddfs][i], ciq[j]);
            }
        }
    }
    // Set Friday athan (can be negative minutes before dhuhr)
    if (parseInt(ciq[5], 10) != 0) {
        document.getElementById('fdp').innerHTML = update_iq(ats[ddfs][2], ciq[5]);
    }
}

// Highlight Friday row on Friday and turn it off the rest of the week
function fridayOnOff() {
    "use strict";
    var today = new Date();
    if (today.getDay() === 5) {
        document.getElementsByTagName("tr")[7].setAttribute("class", "next");
    } else {
        document.getElementsByTagName("tr")[7].setAttribute("class", "");
    }
}

// Return milliseconds untill 'untill'
function getTimeTo(untill) {
    "use strict";
    var rightnow = new Date(), ms = new Date(rightnow.getFullYear(), rightnow.getMonth(), rightnow.getDate(), untill.getHours(), untill.getMinutes(), 0, 0) - rightnow;

    if (ms < 0) {
        ms += 86400000; // add a day
    }
    return ms;
}

// Return milliseconds untill 'untill' -- Don't add next day
// Return negatives
function getTimeToNND(untill) {
    "use strict";
    var rightnow = new Date(), ms = new Date(rightnow.getFullYear(), rightnow.getMonth(), rightnow.getDate(), untill.getHours(), untill.getMinutes(), 0, 0) - rightnow;

    return ms;
}

String.prototype.toHHMMSS = function () {
    "use strict";
    var sec_num = parseInt(this, 10), hours   = Math.floor(sec_num / 3600), minutes = Math.floor((sec_num - (hours * 3600)) / 60), seconds = sec_num - (hours * 3600) - (minutes * 60);

    if (hours   < 10) { hours   = "0" + hours; }
    if (minutes < 10) { minutes = "0" + minutes; }
    if (seconds < 10) { seconds = "0" + seconds; }
    return hours + ':' + minutes + ':' + seconds;
};

function tickToPrayer(time, pn) { // pn = prayer name
    "use strict";
    document.getElementsByTagName("h2")[0].innerHTML = "Remaining to </br>" + pn + " :";

    clearInterval(nextTicker);
    nextTicker = setInterval(function () {
        var x = getTimeTo(time) / 1000;
        if (x > 1) {
            document.getElementById("timerBox").innerHTML = x.toString().toHHMMSS();
        } else {
            clearInterval(nextTicker);
            document.getElementById("timerBox").innerHTML = "";
        }
    }, 500);
}

function getMin(ar) {
    "use strict";
    var i, x = ar[0], dx = 0;
    for (i = 1; i < 7; i += 1) {
        if (ar[i] < x) { x = ar[i]; dx = i; }
    }
    return dx;
}

// To count down to following athan or iqama, then call itself back
// at the next athan or iqama
function countDownToIqama() {
    "use strict";
    var i, setDx, rmDx, prayerName = ['', 'FAJR', 'DHUHR', 'ASR', 'MAGHRIB', 'ISHA', 'SUNRISE', 'MIDNIGHT'], nextIq, nextAth, oneoclock = new Date(), a, xx, fdpHrs, fdpMns;

    a = document.getElementById("fdp").innerHTML;
    xx = a.split(' ')[0];

    fdpHrs = parseInt(xx.split(':')[0], 10);
    if (a.search("PM") > -1 && fdpHrs < 12) { fdpHrs += 12; }
    fdpMns = parseInt(xx.split(':')[1], 10);

    oneoclock.setHours(fdpHrs, fdpMns, 0, 0);

    for (i = 0; i < 7; i += 1) {
        millisTillAth[i] = getTimeTo(athFullTimes[i]);
        millisTillIq[i] = getTimeTo(iqFullTimes[i]);
    }

    // Delay
    millisTillAth[6] += 2000;
    millisTillIq[6] += 2000;

    nextIq = getMin(millisTillIq);
    nextAth = getMin(millisTillAth);

    if (oneoclock.getDay() === 5 && getTimeToNND(oneoclock) < 0) {
        // If Dhuhr Athan or Iqama comes after Jumuah move that to Asr
        if (nextIq === 2) { nextIq = 3; }
        if (nextAth === 2) { nextAth = 3; }
    }

    // Highlight next prayer after page open
    if (nextIq === 0) {
        setDx = 1;
        rmDx = 5;
    } else if (nextIq === 1) {
        setDx = 6;
        rmDx = 1;
    } else if (nextIq === 2) {
        setDx = nextIq;
        rmDx = 6;
    } else if (nextIq === 6) {
        setDx = 7;
        rmDx = 5;
    } else {
        setDx = nextIq;
        rmDx = nextIq - 1;
    }

    if (setDx !== 7) {
        document.getElementsByTagName("tr")[setDx].setAttribute("class", "next");
    }
    document.getElementsByTagName("tr")[rmDx].setAttribute("class", "");


    if (oneoclock.getDay() === 5 && nextAth > 1 && getTimeToNND(oneoclock) >= 0) {
        tickToPrayer(oneoclock, "JUMUAH");
        setTimeout(countDownToIqama, getTimeTo(oneoclock) + 500);

    } else {
        // If between athan and iqama, start ticking to iqama right away
        // April 2018: subtracted 1000 ms to fix iqama/midnight issue
        if (millisTillIq[nextIq] < (millisTillAth[nextAth]-1000)) {
            tickToPrayer(iqFullTimes[nextIq], "IQAMA");
            setTimeout(countDownToIqama, millisTillIq[nextIq] + 500);
        } else { // otherwise, count down to athan
            tickToPrayer(athFullTimes[nextAth], prayerName[setDx]);
            setTimeout(countDownToIqama, millisTillAth[nextAth] + 500);
        }
    }
}

// Run slider section
function runSlider() {
    clearInterval(sliderTicker);
    sliderTicker = setInterval(function() {
    $("#slider").slideUp(3000, function () {
        if($(this).html().indexOf("Fajr") != -1) {
            $("#slider").html("Dhuhr " + ats[ddfs][2].split(' ')[0]);
        } else if($(this).html().indexOf("Dhuhr") != -1) {
            $("#slider").html("Asr " + ats[ddfs][3].split(' ')[0]);
        } else if($(this).html().indexOf("Asr") != -1) {
            $("#slider").html("Maghrib " + ats[ddfs][4].split(' ')[0]);
        } else if($(this).html().indexOf("Maghrib") != -1) {
            $("#slider").html("Isha " + ats[ddfs][5].split(' ')[0]);
        } else if($(this).html().indexOf("Isha") != -1) {
            $("#slider").html("Fajr " + ats[ddfs][0].split(' ')[0]);
        } else {
           $("#slider").html("Fajr " + ats[ddfs][0].split(' ')[0]);
        }

    });
    $("#slider").slideDown(4000);
    }, 8000);
}


function jsreload() {
    "use strict";

    setNewDate();

    if(CLCLT === 0) ddfs += 1;
    if(dremain > 0) dremain -= 1; // avoid falling below 0 with CLCLT
    setAT();
    getPrayerTimes();
    fridayOnOff();
    runSlider();

    setTimeout(jsreload, (24 * 60 * 60 * 1000));
    //document.getElementById("debug").innerHTML = "jsreload </br>";
}

function ClientVsServerDate(i, j) {
  // return 0 for i == j
  //        1 for i > j
  //       -1 for i < j
  if(i == j) return 0;
  else { // if beginning of a new month
    if((i >= 30 && j == 1) || (i == 1 && j >= 30)) {
      if(i == 1) i += 31;
      else j += 31;
    }
    if(i > j) return 1; else return -1;
  }
}

function jsreload_once() {
    "use strict";

    var ClientDay = new Date().getDate();
    if(ClientVsServerDate(ClientDay, ServerDay) == -1) {
      if(CLCLT === 0) ddfs += 1;
      if(dremain > 0) dremain -= 1;
      setAT();
      getPrayerTimes();
    }
    if(ClientVsServerDate(ClientDay, ServerDay) == 0) {
      if(CLCLT === 0) ddfs += 2;
      if(dremain > 0) dremain -= 2;
    }
    if(ClientVsServerDate(ClientDay, ServerDay) == 1) {
      if(CLCLT === 0) ddfs += 3;
      if(dremain > 0) dremain -= 3;
      setAT();
      getPrayerTimes();
    }
    runSlider();
    //document.getElementById("debug").innerHTML = "Client Date: " + ClientDay + " - ServerDate: " + ServerDay + "</br>";

}

function refresh_MN() {
    "use strict";
    var MN = new Date();
    MN.setDate(MN.getDate() + 1);
    MN.setHours(0, 0, 0, 0);
    MN = getTimeTo(MN);

    setTimeout(jsreload, MN);

//    setTimeout(function () {
//        if(navigator.onLine) window.location.reload(true);
//    }, MN+(60*60*1000));

}

refresh_MN();

getPageParms();
setNewDate();
getFAT();
if(CLCLT === 1) setAT();
getPrayerTimes();
fridayOnOff();
//if(CLCLT === 1) runSlider();
jsreload_once();

var lastCheck = 0;
function sleepCheck() {
  var now = new Date().getTime();
  var diff = now - lastCheck;
    if (Math.abs(diff) > 30000) { // a min diff of half a minute is required before a reload
      // alert('took ' + diff + 'ms');
      if(window.navigator.onLine) window.location.reload(true);
    }
    lastCheck = now;
}

window.onload = function () {
    "use strict";

    setTimeout(countDownToIqama, 300);
    setInterval(function () {
        document.getElementById('clockBox').innerHTML = new Date().toTimeString();
    }, 500);

    lastCheck = new Date().getTime();
    setInterval(sleepCheck, 5000); // Check every 5 seconds

//    document.getElementById('debug').innerHTML = " Browser online: " + navigator.onLine;

};