#region << Using Directives >>
using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using System.Threading;
using Volpe.Cafe.EspressoUI.Charts;
using Volpe.Cafe.EspressoUI.ModelCharts;
using Volpe.Cafe.EspressoUI.Themes;
using Volpe.Cafe.EspressoUI.Utils;
using Volpe.Cafe.Resources;
#endregion

namespace Volpe.Cafe.EspressoUI
{
    class SplashScreen : Form
    {

        #region /*** Ctors ***/

        /// <summary>
        /// Initializes a new instance of the <see cref="SplashScreen"/> class.
        /// </summary>
        public SplashScreen()
        {
            this.InitializeComponent();
            this.InitializeOther();
        }

        /// <summary> 
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true, if managed resources should be disposed; false, otherwise.</param>
        protected override void Dispose(bool disposing)
        {
            base.Dispose(disposing);
        }

        #endregion

        #region /*** Methods ***/

        #region /* Designer Generated Code */

        void InitializeComponent()
        {
            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(SplashScreen));
            this.ux_label = new System.Windows.Forms.Label();
            this.ux_chart2 = new Volpe.Cafe.EspressoUI.ModelCharts.ModelChart();
            this.ux_chart1 = new Volpe.Cafe.EspressoUI.ModelCharts.SessionSummaryChart();
            this.SuspendLayout();
            // 
            // ux_label
            // 
            this.ux_label.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
            | System.Windows.Forms.AnchorStyles.Right)));
            this.ux_label.Font = new System.Drawing.Font("Microsoft Sans Serif", 18F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            this.ux_label.Location = new System.Drawing.Point(16, 16);
            this.ux_label.Name = "ux_label";
            this.ux_label.Size = new System.Drawing.Size(424, 64);
            this.ux_label.TabIndex = 0;
            this.ux_label.Text = "Please wait while model resources are being loaded ...";
            // 
            // ux_chart2
            // 
            this.ux_chart2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
            | System.Windows.Forms.AnchorStyles.Right)));
            this.ux_chart2.CategoryAxisDiscreteValues = new string[] {
        "Full-Roll",
        "Some-Roll",
        "No-Roll",
        "Full-Aero",
        "Some-Aero",
        "No-Aero",
        "Full-MR",
        "Some-MR",
        "No-MR",
        "BEV",
        "PHEV",
        "SHEV",
        "MHEV",
        "CVT",
        "DCT",
        "AT",
        "MT",
        "Adv.Eng",
        "Diesel",
        "Turbo",
        "Base.Eng"};
            this.ux_chart2.DisableContextMenu = true;
            this.ux_chart2.GridBackColor = System.Drawing.Color.LightGray;
            this.ux_chart2.GridBorderStyle = System.Windows.Forms.Border3DStyle.RaisedInner;
            this.ux_chart2.GridLinesColor = System.Drawing.Color.Silver;
            this.ux_chart2.GridOrientation = Volpe.Cafe.EspressoUI.Charts.GridOrientation.Swapped;
            this.ux_chart2.GridPadding = new System.Windows.Forms.Padding(8);
            this.ux_chart2.LegendBackColor = System.Drawing.Color.Gainsboro;
            this.ux_chart2.LMBEffect = Volpe.Cafe.EspressoUI.Charts.AnimationEffect.Rotate;
            this.ux_chart2.LMBTrackHTravel = false;
            this.ux_chart2.LMBTrackVTravel = false;
            this.ux_chart2.Location = new System.Drawing.Point(456, 8);
            this.ux_chart2.Margin = new System.Windows.Forms.Padding(4);
            this.ux_chart2.Name = "ux_chart2";
            this.ux_chart2.PrimaryAxisMaxValue = 1D;
            this.ux_chart2.PrimaryAxisMinValue = 0D;
            this.ux_chart2.PrimaryAxisNumberFormat = "0%";
            this.ux_chart2.PrimaryAxisTickMarks = 5;
            this.ux_chart2.RMBMinDistanceTracking = 0;
            this.ux_chart2.RMBTrackHTravel = false;
            this.ux_chart2.ShowTitle = false;
            this.ux_chart2.Size = new System.Drawing.Size(256, 464);
            this.ux_chart2.TabIndex = 2;
            this.ux_chart2.Title = "";
            this.ux_chart2.TrackArrowKeys = false;
            this.ux_chart2.ZoomFactor = 1F;
            // 
            // ux_chart1
            // 
            this.ux_chart1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
            | System.Windows.Forms.AnchorStyles.Left) 
            | System.Windows.Forms.AnchorStyles.Right)));
            this.ux_chart1.CategoryAxisDiscreteValues = new string[] {
        "2018",
        "2019",
        "2020",
        "2021",
        "2022"};
            this.ux_chart1.CategoryAxisLabel = "Model Year";
            this.ux_chart1.DisableContextMenu = true;
            this.ux_chart1.GridBackColor = System.Drawing.Color.LightGray;
            this.ux_chart1.GridBorderStyle = System.Windows.Forms.Border3DStyle.RaisedInner;
            this.ux_chart1.GridLinesColor = System.Drawing.Color.Silver;
            this.ux_chart1.GridPadding = new System.Windows.Forms.Padding(8);
            this.ux_chart1.LegendBackColor = System.Drawing.Color.Gainsboro;
            this.ux_chart1.LMBEffect = Volpe.Cafe.EspressoUI.Charts.AnimationEffect.Rotate;
            this.ux_chart1.LMBTrackVTravel = false;
            this.ux_chart1.Location = new System.Drawing.Point(8, 88);
            this.ux_chart1.Margin = new System.Windows.Forms.Padding(4);
            this.ux_chart1.MfrFilter = -1;
            this.ux_chart1.Name = "ux_chart1";
            this.ux_chart1.PlotMfr = true;
            this.ux_chart1.PrimaryAxisLabel = "mpg";
            this.ux_chart1.PrimaryAxisMaxValue = 15D;
            this.ux_chart1.PrimaryAxisMinValue = 0D;
            this.ux_chart1.PrimaryAxisNumberFormat = "0.0";
            this.ux_chart1.PrimaryAxisSeriesStyle = Volpe.Cafe.EspressoUI.Charts.ChartStyle.Line;
            this.ux_chart1.RMBMinDistanceTracking = 0;
            this.ux_chart1.RMBTrackHTravel = false;
            this.ux_chart1.SecondaryAxisLabel = "$ (m)";
            this.ux_chart1.SecondaryAxisMaxValue = 300D;
            this.ux_chart1.SecondaryAxisMinValue = 0D;
            this.ux_chart1.SecondaryAxisNumberFormat = "0";
            this.ux_chart1.SecondaryAxisSeriesStyle = Volpe.Cafe.EspressoUI.Charts.ChartStyle.Bar;
            this.ux_chart1.ShowSecondaryAxis = true;
            this.ux_chart1.ShowTitle = false;
            this.ux_chart1.Size = new System.Drawing.Size(440, 384);
            this.ux_chart1.TabIndex = 1;
            this.ux_chart1.Title = "";
            this.ux_chart1.TrackArrowKeys = false;
            this.ux_chart1.ZoomFactor = 1F;
            // 
            // SplashScreen
            // 
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
            this.BackColor = System.Drawing.Color.Silver;
            this.ClientSize = new System.Drawing.Size(720, 480);
            this.ControlBox = false;
            this.Controls.Add(this.ux_chart2);
            this.Controls.Add(this.ux_chart1);
            this.Controls.Add(this.ux_label);
            this.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            this.ForeColor = System.Drawing.Color.Black;
            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
            this.MaximizeBox = false;
            this.MaximumSize = new System.Drawing.Size(720, 480);
            this.MinimizeBox = false;
            this.MinimumSize = new System.Drawing.Size(720, 480);
            this.Name = "SplashScreen";
            this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
            this.Text = "CAFE Model";
            this.ResumeLayout(false);

        }

        #endregion

        void InitializeOther()
        {
            // set app icon
            this.Icon = Program.GetAppIcon();
            // set starting size
            this.MaximumSize = GlobalSettings.SplashScreenSize;
            this.Size        = GlobalSettings.SplashScreenSize;
            this.MinimumSize = GlobalSettings.SplashScreenSize;
            // set font
            Font font = this.ux_label.Font;
            this.ux_label.Font = new Font(font.FontFamily, font.Size * GlobalSettings.DPIScale);
            // apply theme
            Theme.ApplyTheme(this);
            // keep form open
            this.PreventFromClosing = true;
            // adjust chart positioning
            this.AdjustChartPosition();
        }

        void AdjustChartPosition()
        {
            // calculate position adjustments based on splash screen's width
            int w = this.Width;

            if (w < 480)
            {   // hide chart2 if splash screen's width < 480px -- there is not enough room to
                // comfortably show both
                this.ux_chart2.Visible = false;
                // also set chart1 and label to occupy entire splash screen window
                this.ux_chart1.Width = w - 16;
                this.ux_label.Width = w - 32;
            }
            else
            {   // if width >= 480px -- we calculate the adjustment as the Sqrt of width/720,
                // where 720px is the "reference" width for the splash screen
                double adj = Math.Pow(w / 720.0D, 1.25D);
                // first compute width for chart1, then bound everything to it
                // - 440px is the "reference" width for chart1
                // - adjust new width to round at 8px intervals
                int c1w = (int)Math.Ceiling(440 * adj / 8) * 8;
                this.ux_label .Width = c1w - 16;
                this.ux_chart1.Width = c1w;
                this.ux_chart2.Left  = c1w + 16;
                this.ux_chart2.Width = w - c1w - 24;
            }
        }

        protected override void OnLoad(EventArgs e)
        {
            //--- set up chart 1 ---
            this.ux_chart1.UpdateDataSeriesValues(0, new double[] { 28.0, 29.4,  30.9, 32.4,  34.0 });
            this.ux_chart1.UpdateDataSeriesValues(1, new double[] { 25.9, 31.1,  31.1, 31.1,  35.8 });
            this.ux_chart1.UpdateDataSeriesValues(2, new double[] {  2.1,  0.0,   0.0,  1.3,   0.0 });
            this.ux_chart1.UpdateDataSeriesValues(3, new double[] { 48.4,  0.0,   0.0, 27.9,   0.0 });
            this.ux_chart1.UpdateDataSeriesValues(4, new double[] {  0.0, 56.4,  62.0, 55.8, 116.9 });
            this.ux_chart1.UpdateDataSeriesValues(5, new double[] {  0.0, 39.2, -21.9, 45.4,  72.1 });
            this.ux_chart1.UpdateDataSeriesValues(6, new double[] {  0.0,  3.8,  -1.9,  5.9,   8.2 });
            //
            this.ux_chart1.PrimaryAxisMaxValue   =  40;
            this.ux_chart1.SecondaryAxisMinValue = -50;
            this.ux_chart1.SecondaryAxisMaxValue = 150;
            //--- set up chart 2 ---
            this.ux_chart2.AddDataSeries("Tech Application", AxisType.Primary, ChartStyle.Bar);
            this.ux_chart2.AddDataSeries("Tech Utilization", AxisType.Primary, ChartStyle.Bar);
            this.ux_chart2.UpdateDataSeriesValues(0, new double[] { 0.17, 0.55, 0, 0.12, 0.58, 0, 0.46, 0.02, 0, 0.03, 0.07, 0.13, 0.28, 0.07, 0.09, 0, 0, 0.04, 0.05, 0.36, 0 });
            this.ux_chart2.UpdateDataSeriesValues(1, new double[] { 0.27, 0.62, 0.11, 0.12, 0.85, 0.03, 0.46, 0.02, 0.52, 0.03, 0.08, 0.14, 0.31, 0.08, 0.12, 0.74, 0.06, 0.04, 0.11, 0.49, 0.36 });
            //
            base.OnLoad(e);
        }
        protected override void OnShown(EventArgs e)
        {
            this._shownTimestamp = DateTime.Now.Ticks;
            base.OnShown(e);
        }
        protected override void OnClosing(CancelEventArgs e)
        {
            e.Cancel = this.PreventFromClosing; // prevent splash-screen from closing
            base.OnClosing(e);
        }
        protected override void OnPaint(PaintEventArgs e)
        {
            Graphics g = e.Graphics;
            ControlPaint.DrawBorder3D(g, this.ClientRectangle, Border3DStyle.Etched);
            this.PaintChartBorder(g, this.ux_chart1);
            this.PaintChartBorder(g, this.ux_chart2);
            //
            base.OnPaint(e);
        }
        void PaintChartBorder(Graphics g, Chart chart)
        {
            Rectangle rect = chart.Bounds;
            rect.Offset(-1, -1);
            rect.Inflate(2, 2);
            Color c = (Theme.BackColor == Theme.GridLinesColor) ? Theme.GridBackColor : Theme.GridLinesColor;
            ControlPaint.DrawBorder(g, rect, c, ButtonBorderStyle.Solid);
        }

        #endregion

        #region /*** Properties ***/

        static Theme Theme { get { return Theme.Dark; } }

        /// <summary>Gets the amount of milliseconds elapsed since the Splash Screen became visible.</summary>
        public int ElapsedTime { get { return (int)((DateTime.Now.Ticks - this._shownTimestamp) / 10000); } }
        /// <summary>Gets or sets whether the Splash Screen should be prevented from closing while model data is being loaded.</summary>
        public bool PreventFromClosing { get; set; }

        /// <summary>Gets or sets the title string to display in the Splash Screen.</summary>
        public string Title
        {
            get => this.ux_label.Text;
            set
            {
                if (value != null && value.Trim() != this.ux_label.Text)
                {
                    this.ux_label.Text = value.Trim();
                }
            }
        }

        #endregion

        #region /*** Variables ***/

        #region /* UI Variables */

        Label ux_label;
        SessionSummaryChart ux_chart1;
        ModelChart ux_chart2;

        #endregion

        long _shownTimestamp; // timestamp when splash-screen was first shown

        #endregion

    }
}
