// Created with MonoDevelop
//
//    QuickStep: Acquire, view and identify spectra 
//    Copyright (C) 2021 Torsten Schache, Hiperscan GmbH Dresden, Germany
//
//    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/>.

using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Threading.Tasks;
using Cairo;
using Hiperscan.Extensions.ApoIdent.Widgets;
using Hiperscan.GtkExtensions.Widgets;

namespace Hiperscan.Extensions.ApoIdent
{
    public class GuiDesigner
    {
        public event EventHandler BgYPositionChanged = null;
        public event EventHandler MeasuringButtonSizeChanged = null;
        public event EventHandler MeasuringAlignmentChanged = null;

        public event EventHandler OuterLineWidthChanged = null;
        public event EventHandler MenuLineWidthChanged = null;
        public event EventHandler StatebarTopLineWidthChanged = null;
        public event EventHandler StatebarLeftLineWidthChanged = null;
        public event EventHandler StatebarRightLineWidthChanged = null;



        public GuiDesigner()
        {
            this.LoadDefaultImageSurfaces();
            this.LoadIconsForColoring();
            this.LoadIconImages();
            this.LoadIconInactiveImages();


            if (ApoIdentEnvs.GuiColorOff)
            {

                this.LoadingSuccess = false;
                return;
            }

            this.LoadPicturesForColoring();
            if (this.BitmapLoader.LoadSuccess == false)
            {
                this.LoadingSuccess = false;
                return;
            }
        }

        public Gdk.Pixbuf GetIconImage(ApoIdentIcon icon)
        {
            string resource = this.GetIconResource(icon.ToString());
            return this.IconImages[resource];
        }

        public Gdk.Pixbuf GetIconInactiveImage(ApoIdentIcon icon)
        {
            string resource = this.GetIconResource(icon.ToString());
            return this.IconInactiveImages[resource];
        }

        public Dictionary<string, Gdk.Pixbuf> SetIconColor(Gdk.Color color, bool menu_icon)
        {
            string[] names = Enum.GetNames(typeof(ApoIdentIcon));
            Dictionary<string, Gdk.Pixbuf> pictures = new Dictionary<string, Gdk.Pixbuf>();

            foreach(string name in names)
            {
                ApoIdentIcon icon = (ApoIdentIcon)Enum.Parse(typeof(ApoIdentIcon), name);
                if (this.IsMenuIcon(icon) != menu_icon)
                    continue;

                string resource = this.GetIconResource(name);

                Gdk.Size size = this.GetSIconsize(icon);
                Gdk.Pixbuf pixbuf = this.BitmapLoader.SetIconColor(resource, color, size);
                pictures.Add(resource, pixbuf);
            };

            Dictionary<string, Gdk.Pixbuf> tmp = new Dictionary<string, Gdk.Pixbuf>();

            foreach (string resource in pictures.Keys)
            {
                tmp[resource] = pictures[resource];
            }

            return tmp;
        }

        

        public void SetLogoColor(Gdk.Color new_color)
        {
            string resource = System.IO.Path.Combine(this.FileResourcePath, "apo-ident_logo.png");
            this.Logo = this.BitmapLoader.SetPictureColor(resource, new_color);
        }

        private void LoadIconsForColoring()
        {
            string[] names = Enum.GetNames(typeof(ApoIdentIcon));

            foreach (string current in names)
            {
                string resource = this.GetIconResource(current);
                this.BitmapLoader.LoadPicture(resource);

            };
        }

        private void LoadPicturesForColoring()
        {
            string file = System.IO.Path.Combine(this.FileResourcePath, "splash-screen.png");
            this.BitmapLoader.LoadPicture(file, true);

            file = System.IO.Path.Combine(this.FileResourcePath, "background.png");
            this.BitmapLoader.LoadPicture(file, true);

            file = System.IO.Path.Combine(this.FileResourcePath, "apo-ident_logo.png");
            this.BitmapLoader.LoadPicture(file, false);
        }

        private void LoadDefaultImageSurfaces()
        {
            string file = System.IO.Path.Combine(this.FileResourcePath, "splash-screen.png");
            this.SplashScreen = new ImageSurface(file);

            file = System.IO.Path.Combine(this.FileResourcePath, "background.png");
            this.BackGround = new ImageSurface(file);

            file = System.IO.Path.Combine(this.FileResourcePath, "apo-ident_logo.png");
            this.Logo = new ImageSurface(file);
        }

        private void LoadIconImages()
        {
            foreach (ApoIdentIcon item in Enum.GetValues(typeof(ApoIdentIcon)))
            {
                string resource = this.GetIconResource(item.ToString());

                Gdk.Size size = this.GetSIconsize(item);
                Gdk.Pixbuf pixbuf = new Gdk.Pixbuf(null, resource, size.Width,size.Height);
                this.IconImages.Add(resource, pixbuf);
            }
        }

        private void LoadIconInactiveImages()
        {
            Gdk.Color color = new Gdk.Color(125, 125, 255);
            this.IconInactiveImages = this.SetIconColor(color, true);
            Dictionary<string, Gdk.Pixbuf> tmp = this.SetIconColor(color, false);
            foreach (string key in tmp.Keys)
                this.IconInactiveImages.Add(key, tmp[key]);
        }



        private Gdk.Size GetSIconsize(ApoIdentIcon icon)
        {
            int x, y;
            Gtk.Icon.SizeLookup(this.MenuIconSize, out x, out y);

            switch (icon)
            {
                case ApoIdentIcon.ClassifierChange:
                case ApoIdentIcon.DataExchangeLennartz:
                case ApoIdentIcon.DataExchangeLennartzOk:
                case ApoIdentIcon.LabelPrint:
                case ApoIdentIcon.Pdf:
                case ApoIdentIcon.Print:
                case ApoIdentIcon.Save:
                case ApoIdentIcon.SubstanceInfo:
                case ApoIdentIcon.SubstanceWarning:
                case ApoIdentIcon.AbortReferencing:
                    Gtk.Icon.SizeLookup(this.ButtonIconSize, out x, out y);
                    break;

                default:
                    break;
            }

            return new Gdk.Size(x, y);
        }

        private bool IsMenuIcon(ApoIdent.ApoIdentIcon icon)
        {
            bool is_menu = true;
            switch (icon)
            {
                case ApoIdentIcon.ClassifierChange:
                case ApoIdentIcon.DataExchangeLennartz:
                case ApoIdentIcon.LabelPrint:
                case ApoIdentIcon.Pdf:
                case ApoIdentIcon.Print:
                case ApoIdentIcon.Save:
                case ApoIdentIcon.SubstanceInfo:
                case ApoIdentIcon.SubstanceWarning:
                    is_menu = false;
                    break;

                default:
                    break;
            }

            return is_menu;
        }

        public void SetValidatedWidgetColor(OutLinedValidatedWidget widget)
        {
            widget.OkColor = this.MandatoryOkColor;
        }

        public void SetValidatedEntryColor(OutLinedRegexEntry entry)
        {
            entry.OkColor = this.EntryMandatoryOkColor;
            entry.OkFocusedColor = this.EntryMandatoryOkSelectedColor;
        }

        private string GetIconResource(string icon)
        {
            return String.Format("Hiperscan.Extensions.ApoIdent.ApoIdentApplication.Icons.{0}.png", icon);
        }

        private string FileResourcePath
        {
            get
            {
                string resource = System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
                return System.IO.Path.Combine(resource, "GuiDesigner");
            }
        }

        public Gtk.IconSize MenuIconSize { get; set; } = Gtk.IconSize.Dialog;
        public Gtk.IconSize ButtonIconSize { get; set; } = Gtk.IconSize.LargeToolbar;

        public ImageSurface BackGround { get; set; }
        public ImageSurface Logo { get; set; }
        public ImageSurface SplashScreen { get; set; }

        private Dictionary<string, Gdk.Pixbuf> IconImages { get; set; } = new Dictionary<string, Gdk.Pixbuf>();
        private Dictionary<string, Gdk.Pixbuf> IconInactiveImages { get; set; } = new Dictionary<string, Gdk.Pixbuf>();


        public BitimapLoader BitmapLoader { get; set; } = new BitimapLoader();
        public bool LoadingSuccess { get; private set; } = true;

        private Gdk.Color MandatoryOkColor { get; set; } = ApoIdentColors.WHITE;
        private Gdk.Color MandatoryErrorColor { get; set; } = ApoIdentColors.WHITE;

        private Gdk.Color EntryMandatoryOkColor { get; set; } = ApoIdentColors.lIGHT_GRAY;
        private Gdk.Color EntryMandatoryOkSelectedColor { get; set; } = ApoIdentColors.GRAY;
        private Gdk.Color EntryMandatoryErrorColor { get; set; } = ApoIdentColors.lIGHT_GRAY;
        private Gdk.Color EntryMandatoryErrorSelectedColor { get; set; } = ApoIdentColors.GRAY;

        private double bg_y_position = 36;
        public double BgYPosition
        {
            get
            {
                return this.bg_y_position;
            }
            set
            {
                this.bg_y_position = value;
                this.BgYPositionChanged?.Invoke(this, EventArgs.Empty);
            }
        }

        private int measuring_button_size = MeasuringButton.DEFAULT_SIZE;
        public int MeasuringButtonSize
        {
            get
            {
                return this.measuring_button_size;
            }
            set
            {
                this.measuring_button_size = value;
                this.MeasuringButtonSizeChanged?.Invoke(this, EventArgs.Empty);
            }
        }

        private double measuring_alignment = MeasuringButton.DEFAULT_ALIGNMENT;
        public double MeasuringAlignment
        {
            get
            {
                return this.measuring_alignment;
            }
            set
            {
                this.measuring_alignment = value;
                this.MeasuringAlignmentChanged?.Invoke(this, EventArgs.Empty);
            }
        }

        private int outer_line_width = Animation.LINE_WIDTH;
        public int OuterLineWidth
        {
            get
            {
                return this.outer_line_width;
            }
            set
            {
                this.outer_line_width = value;
                this.OuterLineWidthChanged?.Invoke(this, EventArgs.Empty);
            }
        }

        private int menu_line_width = Animation.LINE_WIDTH;
        public int MenuLineeWidth
        {
            get
            {
                return this.menu_line_width;
            }
            set
            {
                this.menu_line_width = value;
                this.MenuLineWidthChanged?.Invoke(this, EventArgs.Empty);
            }
        }

        private int sb_top_line_width = 0;
        public int StateBarTopLineWidth
        {
            get
            {
                return this.sb_top_line_width;
            }
            set
            {
                this.sb_top_line_width = value;
                this.StatebarTopLineWidthChanged?.Invoke(this, EventArgs.Empty);
            }
        }

        private int sb_left_line_width = Animation.LINE_WIDTH;
        public int StateBarLeftLineWidth
        {
            get
            {
                return this.sb_left_line_width;
            }
            set
            {
                this.sb_left_line_width = value;
                this.StatebarLeftLineWidthChanged?.Invoke(this, EventArgs.Empty);
            }
        }

        private int sb_right_line_width = 0;
        public int StateBarRightLineWidth
        {
            get
            {
                return this.sb_right_line_width;
            }
            set
            {
                this.sb_right_line_width = value;
                this.StatebarRightLineWidthChanged?.Invoke(this, EventArgs.Empty);
            }
        }
    }
}
