/*******************************************************************************
**	Author: Peter McCutcheon
**	Date Created:  3/31/2017
**	Last Modified: 12/02/2017
**
**------------------------------------------------------------------------------
**Description of Code:
**
**
********************************************************************************/

function pageLoaded()
{
    var frmtTime = d3.timeParse(":%S");
        
	btnGenPlot = document.getElementById("btnGenPlot");
	btnGenPlot.addEventListener("click", function () {getDataForGraph("daily", "")}, false);
    
	apRequest = new XMLHttpRequest();
	apRequest.open("POST", "../php/getAirportList.php");
	apRequest.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");	
	if (!apRequest)
	{
		alert("Error - Ajax object not created, browser may not support Ajax.");
		return false;
	}
	apRequest.onreadystatechange = function ()
	{
		if (apRequest.readyState == 4 && apRequest.status === 200)
		{
			if (apRequest.responseText != null)
			{
                var apData = JSON.parse(apRequest.responseText);
                var airportSelect = document.getElementById("airportselect");
                for (var i = 0; i < apData.apID.length; i++)
                {
                    var opt = document.createElement("option");
                    opt.setAttribute("value", apData.apID[i]);
                    opt.text = apData.apDesc[i];
                    airportSelect.appendChild(opt);
                }
                
			}
		}
		else
		{
			if (apRequest.status != 200)
			{
				alert("AJAX Error: " + apRequest.readyState + " --- " + apRequest.status);
			}
		}
	};
	//
	// Send the ajax request to the server.
	//
    apRequest.send(); 

	alRequest = new XMLHttpRequest();
	alRequest.open("POST", "../php/getAirlineList.php");
	alRequest.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");	
	if (!alRequest)
	{
		alert("Error - Ajax object not created, browser may not support Ajax.");
		return false;
	}
	alRequest.onreadystatechange = function ()
	{
		if (alRequest.readyState == 4 && alRequest.status === 200)
		{
			if (alRequest.responseText != null)
			{
                var alData = JSON.parse(alRequest.responseText);
                var airlineSelect = document.getElementById("airlineselect");
                for (var i = 0; i < alData.alID.length; i++)
                {
                    var opt = document.createElement("option");
                    opt.setAttribute("value", alData.alID[i]);
                    opt.text = alData.alDesc[i];
                    airlineSelect.appendChild(opt);
                }                
			}
		}
		else
		{
			if (alRequest.status != 200)
			{
				alert("AJAX Error: " + alRequest.readyState + " --- " + alRequest.status);
			}
		}
	};
	//
	// Send the ajax request to the server.
	//
    alRequest.send();     
}

function getDataForGraph(chartToGenerate, selectDate, flightNum)
{
    //  Date to string conversion.
    var strDate = d3.timeFormat("%Y-%m-%d");
    
    //  String to date conversion.
    var parseTime = d3.timeParse("%Y-%m-%d");
    
	//
	//	Gather the form information to send in the Ajax request to generate the plot per the user.
    //  Get the user selection for the chart.  This will be used to create
    //  a an Ajax message to select the desired data from the database.
    //
    var airportSelected = document.getElementById("airportselect").value;
    var airlineSelected = document.getElementById("airlineselect").value;
    var startDate = document.getElementById("startdate").value;
    var endDate = document.getElementById("enddate").value;
    //
    //  Get the type of chart, from the DOM, that the user wants.
    //
    var plotCircle = document.getElementById("plotcircle");
    var plotBar = document.getElementById("plotbar");
    if (plotCircle.checked)
    {
        var chartType = "C";
    }
    else
    {
        if (plotBar.checked)
        {
            var chartType = "B";
        }
        else
        {
            alert("You did not select a chart type, please select one.");
            return;
        }
    }

	var msg = "";
	//
	//	First clear out the div that contains the chart in preparation for the new plot.
	//	Then set up the Ajax message based on the chart that will be generated.
	//
    if (chartToGenerate == "daily")
    {
        chartImageDiv = document.getElementById("chartimage");
        chartImageDiv.innerHTML = "";        
        msg = "type=" + chartToGenerate + "&airport=" + airportSelected + "&airline=" + airlineSelected + "&startdate=" + startDate + "&enddate=" + endDate;
        alert("Retrieving flight information, this could take a minute or two...");
    }
    else
    {
        if (chartToGenerate == "detail")
        {
            chartImageDiv = document.getElementById("detailimage")
            chartImageDiv.innerHTML = "";            
            //
            //  On the detail for a given day force the graph to always be bar, regardless of what was selected.
            //  This is so the flight numbers display ok, otherwise on the circle graph they can all run together.
            //
            chartType = "B";
            //selectDate = startDate.substring(0, startDate.lastIndexOf("-"));
            //selectDate = selectDate + "-" + day;
            selectDate = strDate(selectDate);
            msg = "type=" + chartToGenerate + "&airport=" + airportSelected + "&airline=" + airlineSelected + "&selectdate=" + selectDate;
        }
        else
        {
            if (chartToGenerate == "flight")
            {
                chartImageDiv = document.getElementById("flightimage")
                chartImageDiv.innerHTML = "";
                //selectDate = startDate.substring(0, startDate.lastIndexOf("-"));
                var tmpDate = parseTime(selectDate);
                selectDate = strDate(tmpDate);
                msg = "type=" + chartToGenerate + "&airport=" + airportSelected + "&airline=" + airlineSelected + "&selectdate=" + selectDate + "&flightnumber=" + flightNum;   
            }
        }
    }
	
	//
	//	Create the Ajax request and send it with our generated message.
	//
	frmrequest = new XMLHttpRequest();
    frmrequest.open("POST", "../php/getFlightData.php");        
	frmrequest.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
	if (!frmrequest)
	{
		alert("Error - Ajax object not created, browser may not support Ajax.");
		return false;
	}
	frmrequest.onreadystatechange = function ()
	{
		if (frmrequest.readyState == 4 && frmrequest.status === 200)
		{
			if (frmrequest.responseText != null)
			{
                if (frmrequest.responseText == "0 results")
                {
                    alert("No flights for the data selection. Please try a different selection.");
                    return;
                }
                if (chartToGenerate == "daily")
                {
                    var chartImageDiv = document.getElementById("chartimage");                    
                }
                else
                {
                    var chartImageDiv = document.getElementById("detailimage");                                        
                }
                var flightData = JSON.parse(frmrequest.responseText);
                if (chartToGenerate == "daily" || chartToGenerate == "detail")
                {
                    var ret = generateGraph(chartType, flightData, chartImageDiv, chartToGenerate, selectDate)
                    if (ret)
                    {
                        alert("Error encountered attempting to generate the graph.");
                    }
                }
                else
                {
                    if (chartToGenerate == "flight")
                    {
                        ret = displayFlightInfo(flightData);
                    }
                    else
                    {
                        alert("We are back with our specific flight data.");
                    }
                }
			}
		}
		else
		{
			if (frmrequest.status != 200)
			{
				alert("AJAX Error: " + frmrequest.readyState + " --- " + frmrequest.status + " text " + frmrequest.responseText);
			}
		}
	}.bind(chartType);
	//
	// Send the ajax request to the server.
	//
	frmrequest.send(msg);
}

function generateGraph(typ, fd, ci, chartToGenerate, sDate)
{
    var margin = {"top": 30, "right": 30, "bottom": 30, "left": 40},
        height = 500 - margin.top - margin.bottom,
        width = 800 - margin.right - margin.left;
    var hDiv2 = height / 2;
    var padding = 40;
    var barPadding = 1;
    var circlePadding = 20;
    var hScaleFactor = 4;
    var txtTitle = "";
    var tipText = "";
    var xScale, yScale, xAxis, yAxis;  //Empty, for now
    var flightData = new Array(new Object());
    
    var startDate = document.getElementById("startdate").value;
    var endDate = document.getElementById("enddate").value;                

    // For converting strings to dates.
    var parseTime = d3.timeParse("%Y-%m-%d");

	//For converting Dates to strings
	var formatTime = d3.timeFormat("%d");
    var formatNiceDate = d3.timeFormat("%B %d, %Y");
    
	//Function for converting CSV values from strings to Dates and numbers
    if (chartToGenerate == "daily")
    {
        flightData[0] = {'xValue': parseTime(fd[0].xValue), 'yValue': parseInt(fd[0].yValue)};        
        txtTitle = "Flight Delay for " + formatNiceDate(parseTime(startDate)) + " To " + formatNiceDate(parseTime(endDate));
        tipText = "Date: ";
    }
    else
    {
        if (chartToGenerate == "detail")
        {
            flightData[0] = {'xValue': fd[0].xValue, 'yValue': parseInt(fd[0].yValue)};
            txtTitle = "Flight Information for " + formatNiceDate(parseTime(sDate));
            tipText = "Flight Number: ";
        }
    }
    for (var i = 1; i < fd.length; i++)
    {
        if (chartToGenerate == "daily")
        {
            flightData.push({'xValue': parseTime(fd[i].xValue), 'yValue': parseInt(fd[i].yValue)});            
        }
        else
        {
            flightData.push({'xValue': fd[i].xValue, 'yValue': parseInt(fd[i].yValue)});                        
        }
    }
    
    //***************************************************************************
    //***************************************************************************
 
    //Convert the array of objects to an object with arrays.
    var ds = {"xValue": new Array(), "yValue": new Array()};
    for (var i = 0; i < flightData.length; i++)
    {
        ds.xValue.push(flightData[i].xValue);
        ds.yValue.push(+flightData[i].yValue);
    }

	var svg = d3.select("#chartimage")
				.append("svg")
				.attr("width", width + margin.right + margin.left)
				.attr("height", height + margin.top + margin.bottom)
                .append("g")
                    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
                
    var dMax = d3.max(flightData, function(d) {
                    return d.yValue;
    });
    
    var dMin = d3.min(flightData, function(d) {
                    return d.yValue;
    });
        
    if (typ == "C")
    {

        //
        //  Set up the y-axis scale.
        //
        var yScale = d3.scaleLinear()
                    .domain([dMin, dMax])
                    .range([height, 0]);
        
        //
        //  set up the x-axis scale.
        //
        var ordScale = d3.scalePoint()
                        .domain(ds.xValue)
                        .range([margin.left,width]);
              
        //
        //  This graph actually is an implementation of a scatterplot.
        //  Here we just make the area of the circles dependent
        //  on there y-value.
        //
        //  Generate all of the circle for the scatterplot graph.
        //
        svg.selectAll("circle")
            .data(flightData)
            .enter()
            .append("circle")
            .attr("cx", function(d, i) {
                return ordScale(d.xValue);
            })
            .attr("cy", function(d) {
                if (d.yValue < 0)
                {
                    return yScale(d.yValue);
                }
                else
                {
                    return yScale(d.yValue);    
                }
            })
            .attr("r", function(d) {return Math.sqrt(Math.abs(d.yValue))})
            .attr("fill", function(d) {
                if (d.yValue < 0)
                {
                    return "yellow";
                }
                else
                {
                    return "red";
                }
            })
            .on("mouseover", function() {
                        d3.select(this).attr("fill", "green")
            })
            .on("mouseout", function(d, i) {
                        d3.select(this).attr("fill", function(d) {
                                                if (d.yValue < 0)
                                                {
                                                    return "yellow";
                                                }
                                                else
                                                {
                                                    return "red";
                                                }
                        })
            })
            .on("click", function(d) {if (chartToGenerate == "daily") getDataForGraph("detail", d.xValue, ""); else if (chartToGenerate == "detail") getDataForGraph("flight", sDate, d.xValue);});
        
        var txtElem = svg.selectAll("text")
            .data(flightData)
            .enter()
            .append("text")
            .text(function(d){return formatTime(d.xValue);})
            .attr("x", function(d, i) {return ordScale(d.xValue) + 4;})
            .attr("y", function(d) {
                if (d.yValue < 0)
                {
                    return yScale(d.yValue);
                }
                else
                {
                    return yScale(d.yValue);
                }
            })
            .attr("font-family", "sans-serif")
            .attr("font-size", "20px")
            .attr("fill", "steelblue");
        
        var xAxis1 = d3.axisBottom()
                        .scale(ordScale)
                        .tickSize(-height,0,0)
                        .tickFormat("");
                        
        svg.append("g")
            .attr("class", "xAxis")
            .attr("transform", "translate(0," + height + ")")
            .call(xAxis1);

        var yAxisPos = d3.axisLeft()
                        .scale(yScale)
                        .tickSize(-width,0,0);
        var yAxisNeg = d3.axisLeft()
                        .scale(yScale)
                        .tickSize(-width,0,0);

        svg.append("g")
            .attr("class", "yAxis")
            .attr("transform", "translate(" + padding + ", 0)")
            .call(yAxisPos);
            
        svg.append("g")
            .attr("class", "yAxis")
            .attr("transform", "translate(" + padding + ", 0)")
            .call(yAxisNeg);
            
        svg.append("text")
            .attr("x", yScale(0)-30)
            .attr("y", margin.left - 30)
            .text("Minutes")
            .attr("text-anchor", "middle")
            .attr("font-size", "20px")
            .attr("fill", "steelblue")
            .attr("transform", "rotate(90)");
        
        svg.append("text")
        .attr("x", (width / 2))             
        .attr("y", 0 - (margin.top / 2))
        .attr("text-anchor", "middle")  
        .style("font-size", "20px")  
        .text(txtTitle)
        .attr("font-family", "sans-serif")
        .attr("fill", "steelblue");
            
    }
    else
    {
        var yScale = d3.scaleLinear()
                    .domain([dMin, dMax])
                    .range([height, 0]);
                    
        var xScale = d3.scaleBand()
                        .domain(d3.range(flightData.length))
                        .range([margin.left, width])
                        .round(true)
                        .paddingInner(0.1);
                        

        svg.selectAll("rect")
            .data(flightData)
            .enter()
            .append("rect")
            .attr("x", function(d, i) {return xScale(i);})
            .attr("width", xScale.bandwidth())
            .attr("y", function(d) {if (d.yValue < 0) return yScale(0); else return yScale(d.yValue);})
            .attr("height", function(d) {return yScale(0) - yScale(Math.abs(d.yValue));})
            .attr("fill", function(d) {if (d.yValue < 0) return "yellow"; else return "red";})
            .on("mouseover", function() {
                        d3.select(this).attr("fill", "green")})
            .on("mouseout", function(d, i) {
                        d3.select(this).attr("fill", function(d) {
                                                if (d.yValue < 0)
                                                {
                                                    return "yellow";
                                                }
                                                else
                                                {
                                                    return "red";
                                                }
                        })
            })
            .on("click", function(d) {if (chartToGenerate == "daily") getDataForGraph("detail", d.xValue, ""); else if (chartToGenerate == "detail") getDataForGraph("flight", sDate, d.xValue);})
            .append("title")
            .text(function(d) {if (chartToGenerate == "daily") return tipText + formatNiceDate(d.xValue); else return tipText + d.xValue;});
    
        /* var txtElem = svg.selectAll("text")
            .data(flightData)
            .enter()
            .append("text")
            .text(function(d){return formatTime(d.xValue);})
            .attr("x", function(d, i) {return xScale(i) + ((xScale.bandwidth()) / 2) - 4;})
            .attr("y", function(d) {
                if (d.yValue < 0)
                {
                    return yScale(0);
                }
                else
                {
                    return yScale(0);
                }
            })
            .attr("font-family", "sans-serif")
            .attr("font-size", "18px")
            .attr("fill", "white"); */
                   
        var yAxisPos = d3.axisLeft()
                        .scale(yScale)
                        .tickSize(-width,0,0);

        svg.append("g")
            .attr("class", "yAxis")
            .attr("transform", "translate(" + padding + ", 0)")
            .call(yAxisPos);
            
        svg.append("text")
            .attr("x", yScale(0)-30)
            .attr("y", margin.left - 30)
            .text("Minutes")
            .attr("text-anchor", "middle")
            .attr("font-size", "20px")
            .attr("fill", "steelblue")
            .attr("transform", "rotate(90)");

        svg.append("text")
        .attr("x", (width / 2))             
        .attr("y", 0 - (margin.top / 2))
        .attr("text-anchor", "middle")  
        .style("font-size", "20px")  
        .text(txtTitle)
        .attr("font-family", "sans-serif")
        .attr("fill", "steelblue");
            
    }       
}

function displayFlightInfo(data)
{
    var flightInfo = "";
    var flightDelay;
    
    flightInfo = data[data.length-1].yValue.split("|");
    var flightInfoLen = flightInfo.length
    var flightInfoDiv = document.getElementById("flightinfo")
    
    flightInfoDiv.innerHTML = "";
    
    var totalTime = 0;
    var delayTime = 0;
    var numData = [];
    for (var i = 0; i < data.length-2; i++)
    {
        delayTime = parseFloat(data[i].yValue);
        numData[i] = delayTime
        totalTime = totalTime + delayTime;
    }
    var aveTime = Math.round(totalTime / (data.length - 1));
    var maxTime = d3.max(numData, function(d) {return d;});
    var minTime = d3.min(numData, function(d) {return d;});

    //
    //  Create the form and the fieldset that will display the flight information.
    //
    var flightForm = document.createElement("form");
    flightForm.setAttribute("class","flightform");
    var flightFldSet = document.createElement("fieldset");
    var fldsetLegend = document.createElement("legend");
    var txtNode = document.createTextNode("Fligh Number: " + flightInfo[flightInfoLen-1]);
    fldsetLegend.appendChild(txtNode);
    flightFldSet.appendChild(fldsetLegend)

    //
    //  Create the paragraph element for the first form row.
    //
    var p1 = document.createElement("p");
    p1.setAttribute("class", "formrow");
    //
    //  Average delay for the year for flight number.
    //
    var aveLabel = document.createElement("label");
    var aveText = document.createTextNode("Average Delay:");
    aveLabel.appendChild(aveText);
    aveLabel.setAttribute("class", "formcelllbl");
    var aveInput = document.createElement("input");
    aveInput.setAttribute("class", "formcellinp");
    aveInput.setAttribute("value", aveTime);
    p1.appendChild(aveLabel);
    p1.appendChild(aveInput);
    
    //
    //  Minimum delay for the year for flight number.
    //
    var minLabel = document.createElement("label");
    var minText = document.createTextNode("Minimum Delay:");
    minLabel.appendChild(minText);
    minLabel.setAttribute("class", "formcelllbl");
    var minInput = document.createElement("input");
    minInput.setAttribute("class", "formcellinp");
    minInput.setAttribute("value", minTime);
    p1.appendChild(minLabel);
    p1.appendChild(minInput);
    
    //
    //  Maximum delay for the year for flight number.
    //
    var maxLabel = document.createElement("label");
    var maxText = document.createTextNode("Maximum Delay:");
    maxLabel.appendChild(maxText);
    maxLabel.setAttribute("class", "formcelllbl");
    var maxInput = document.createElement("input");
    maxInput.setAttribute("class", "formcellinp");
    maxInput.setAttribute("value", maxTime);
    p1.appendChild(maxLabel);
    p1.appendChild(maxInput);
    flightFldSet.appendChild(p1);
    
    //
    //  Create the paragraph element for the second form row.
    //
    var p2 = document.createElement("p");
    p2.setAttribute("class", "formrow");
    //
    //  Airplane tail number.
    //
    var tnLabel = document.createElement("label");
    var tnText = document.createTextNode("Tail Number:");
    tnLabel.appendChild(tnText);
    tnLabel.setAttribute("class", "formcelllbl");
    var tnInput = document.createElement("input");
    tnInput.setAttribute("class", "formcellinp");
    tnInput.setAttribute("value", flightInfo[0]);
    p2.appendChild(tnLabel);
    p2.appendChild(tnInput);
    
    //
    //  Flight destination.
    //
    var destLabel = document.createElement("label");
    var destText = document.createTextNode("Destination:");
    destLabel.appendChild(destText);
    destLabel.setAttribute("class", "formcelllbl");
    var destInput = document.createElement("input");
    destInput.setAttribute("class", "formcellinp");
    destInput.setAttribute("value", flightInfo[1]);
    p2.appendChild(destLabel);
    p2.appendChild(destInput);
    
    //
    //  Flight delay time.
    //
    var fdLabel = document.createElement("label");
    var fdText = document.createTextNode("Flight Delay:");
    fdLabel.appendChild(fdText);
    fdLabel.setAttribute("class", "formcelllbl");
    var fdInput = document.createElement("input");
    fdInput.setAttribute("class", "formcellinp");
    fdInput.setAttribute("value", flightInfo[2]);
    p2.appendChild(fdLabel);
    p2.appendChild(fdInput);
    flightFldSet.appendChild(p2);
    
    //
    //  Create the paragraph element for the third form row.
    //
    var p3 = document.createElement("p");
    p3.setAttribute("class", "formrow");
    //
    //  Carrier delay time.
    //
    var cdLabel = document.createElement("label");
    var cdText = document.createTextNode("Carrier Delay:");
    cdLabel.appendChild(cdText);
    cdLabel.setAttribute("class", "formcelllbl");
    var cdInput = document.createElement("input");
    cdInput.setAttribute("class", "formcellinp");
    cdInput.setAttribute("value", flightInfo[3]);
    p3.appendChild(cdLabel);
    p3.appendChild(cdInput);

    //
    //  Weather delay time.
    //
    var wdLabel = document.createElement("label");
    var wdText = document.createTextNode("Weather Delay:");
    wdLabel.appendChild(wdText);
    wdLabel.setAttribute("class", "formcelllbl");
    var wdInput = document.createElement("input");
    wdInput.setAttribute("class", "formcellinp");
    wdInput.setAttribute("value", flightInfo[4]);
    p3.appendChild(wdLabel);
    p3.appendChild(wdInput);
    flightFldSet.appendChild(p3);
    
    //
    //  Create the paragraph element for the fourth form row.
    //
    var p4 = document.createElement("p");
    p4.setAttribute("class", "formrow");
    //
    //  Security delay time.
    //
    var sdLabel = document.createElement("label");
    var sdText = document.createTextNode("Security Delay:");
    sdLabel.appendChild(sdText);
    sdLabel.setAttribute("class", "formcelllbl");
    var sdInput = document.createElement("input");
    sdInput.setAttribute("class", "formcellinp");
    sdInput.setAttribute("value", flightInfo[5]);
    p4.appendChild(sdLabel);
    p4.appendChild(sdInput);
    
    //
    //  NAS delay time.
    //
    var ndLabel = document.createElement("label");
    var ndText = document.createTextNode("NAS Delay:");
    ndLabel.appendChild(ndText);
    ndLabel.setAttribute("class", "formcelllbl");
    var ndInput = document.createElement("input");
    ndInput.setAttribute("class", "formcellinp");
    ndInput.setAttribute("value", flightInfo[6]);
    p4.appendChild(ndLabel);
    p4.appendChild(ndInput);
    flightFldSet.appendChild(p4);

    //
    //  Create the paragraph element for the fifth form row.
    //
    var p5 = document.createElement("p");
    p5.setAttribute("class", "formrow");
    //
    //  Late Aircraft delay time.
    //
    var laLabel = document.createElement("label");
    var laText = document.createTextNode("Late Aircraft Delay:");
    laLabel.appendChild(laText);
    laLabel.setAttribute("class", "formcelllbl");
    var laInput = document.createElement("input");
    laInput.setAttribute("class", "formcellinp");
    laInput.setAttribute("value", flightInfo[6]);
    p5.appendChild(laLabel);
    p5.appendChild(laInput);
    flightFldSet.appendChild(p5);

    //
    //  Finally append the field set to the form.
    //
    flightForm.appendChild(flightFldSet);
    flightInfoDiv.appendChild(flightForm);

}