using System.Collections.Generic;
using Consulenza.ReportWriter.Business.Entity;
using Dundas.Charting.WebControl;
using Consulenza.ReportWriter.Business.OBJ_PDF;
using System.Drawing;
using System.Linq;


namespace Consulenza.ReportWriter.Business.CHART_PDF
{
    public abstract class ChartPDF : ObjectPDF
    {
        private List<ObjectPDF> _elements = new List<ObjectPDF>();
        private Chart _chartbase = new Chart();
        private List<Marker> _markers = new List<Marker>();
        private float _x;
        private float _y;
        private float _scale = 1;

        private bool _showlabelpoints = true;

        /// <summary>
        /// Lista di ObjectPDF di cui si compone il chart
        /// </summary>
        public List<ObjectPDF> Elements
        {
            get { return _elements; }
            set { _elements = value; }
        }

        /// <summary>
        /// Imposta o recupera l'oggetto chart base.
        /// </summary>
        public Chart ChartBase
        {
            get { return _chartbase; }
            set { _chartbase = value; }
        }

        /// <summary>
        /// Nome del grafico
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// Tipo di grafico
        /// </summary>
        public ChartTypePdf ChartType { get; set; }

        /// <summary>
        /// X
        /// </summary>
        public float X
        {
            get { return _x; }
            set { _x = value; }
        }

        /// <summary>
        /// Y
        /// </summary>
        public float Y
        {
            get { return _y; }
            set { _y = value; }
        }

        /// <summary>
        /// Scala in cui viene renderizzata l'immagine
        /// </summary>
        public float Scale
        {
            get { return _scale; }
            set { _scale = value; }
        }

        /// <summary>
        /// Imposta o recupera la larghezza
        /// </summary>
        public float Width { get; set; }

        /// <summary>
        /// Imposta o recupera l'altezza
        /// </summary>
        public float Height { get; set; }



        /// <summary>
        /// Recupera l'altezza totale del grafico quando è composto da più elementi
        /// </summary>
        public float TotalHeight { get; set; }
        public float? EntireChartMinAxisXVal { get; set; }
        public string EntireChartMinAxisXValLbl { get; set; }

        private List<Serie> _seriesCollection = null;
        private void GetEntireChartMinAxisXVal(List<Serie> seriesCollection)
        {
            double minimum = 0;
            string lbl = string.Empty;
            try
            {
                foreach (var itemSerie in seriesCollection)
                {
                    double currMin = itemSerie.Points.Min(x => x.Value);
                    var currMinPoint = itemSerie.Points.Where(x => x.Value == currMin).FirstOrDefault();
                    if (currMinPoint != null)
                    {
                        if (currMin < minimum)
                        {
                            minimum = currMin;
                            lbl = currMinPoint.LabelAxisY;
                        }
                    }
                }
            }
            catch { }
            EntireChartMinAxisXValLbl = lbl;
            EntireChartMinAxisXVal = (float)(minimum >= 0 ? 0 : (int)(minimum - 1));
        }

        /// <summary>
        /// Lista di Serie
        /// </summary>
        public List<Serie> SeriesCollection
        {
            get
            {
                return _seriesCollection;
            }
            set
            {
                _seriesCollection = value;
                 GetEntireChartMinAxisXVal(value);
            }
        }

        /// <summary>
        /// Imposta o recupera un bool che indica se mostrare le label su ciascun YValues aggiunto.
        /// Di default = true
        /// </summary>
        public bool ShowLabelPoints
        {
            get { return _showlabelpoints; }
            set { _showlabelpoints = value; }
        }

        public List<Marker> Markers
        {
            get { return _markers; }
            set { _markers = value; }
        }

        /// <summary>
        /// Ritorna la ImagePDF del Chart
        /// </summary>
        /// <returns></returns>
        protected ImagePDF ToImage(bool standarizeSize = false)
        {
            var imgGrafico = new System.IO.MemoryStream();
            if (standarizeSize)
            {
                ChartBase.ImageResolution = 96;
                _chartbase.ImageResolution = 96;
                ChartBase.Height = new System.Web.UI.WebControls.Unit(Height);
                ChartBase.Width = new System.Web.UI.WebControls.Unit(Width);
                ChartBase.ImageResolution = 300;
                _chartbase.ImageResolution = 300;
            }
            else
            {
                // default 96 DPI
                _chartbase.ImageResolution = 300;
            }
            _chartbase.Save(imgGrafico, ChartImageFormat.Png);
            return new ImagePDF(_x, imgGrafico, Height, Width, _y);
        }
    }

    /// <summary>
    /// Rappresenta la Serie
    /// </summary>
    public class Serie
    {
        /// <summary>
        /// Nome della Serie
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// Testo della Serie.
        /// </summary>
        public string Text { get; set; }

        public string LabelStyle { get; set; }

        public bool AutoCalculateLastPointLabelPosition { get; set; }
        /// <summary>
        /// Imposta o recupera il tipo di Serie
        /// </summary>
        public SeriesChartType Type { get; set; }

        /// <summary>
        /// Colore
        /// </summary>
        public ColorPDF Color { get; set; }

        /// <summary>
        /// Lista di Points
        /// </summary>
        public List<Point> Points { get; set; }

        /// <summary>
        /// Imposta o recupera un bool che indica se mostrare il bordo.
        /// Di default = false.
        /// </summary>
        public bool Border { get; set; }

        /// <summary>
        /// Imposta o recupera il colore del bordo.
        /// Di default = White.
        /// </summary>
        public ColorPDF BorderColor { get; set; }

        public ChartDashStyle BorderStyle { get; set; }

        /// <summary>
        /// Imposta o recupera la larghezza del bordo della serie.
        /// Di default = 1.
        /// </summary>
        public float BorderWidth { get; set; }

        /// <summary>
        /// Imposta o recupera la larghezza in percentuale della barra.
        /// Possibili valori compresi "0" e "2".        
        /// Di default = "0.8".        
        /// </summary>
        public string PointWidth { get; set; }

        /// <summary>
        /// Imposta o recupera un bool che indica se mostrare la Serie nella legenda.
        /// Di default = true.
        /// </summary>
        public bool ShowInLegend { get; set; }

        /// <summary>
        /// Imposta o recupera il nome dell'immagine del marcatore
        /// </summary>
        public string MarkerImage { get; set; }
        /// <summary>
        /// Imposta o recupera la size  dell'immagine del marcatore
        /// </summary>
        public int? MarkerSize { get; set; }
        /// <summary>
        /// Costruttore
        /// </summary>
        /// 
        public Dundas.Charting.WebControl.MarkerStyle? MarkerStyle { get; set; }


        public Serie()
        {
            Points = new List<Point>();
            Border = false;
            BorderColor = ColorPDF.Bianco;
            BorderWidth = 1;
            PointWidth = "0.8";
            ShowInLegend = true;
            BorderStyle = ChartDashStyle.Solid;
        }
    }

    /// <summary>
    /// Rappresenta il DataPoint
    /// </summary>
    public class Point
    {
        /// <summary>
        /// Costruttore
        /// </summary>
        public Point()
        {
            Values = new ValuesPointXY(0, 0);
            VerticalAlignment = VerticalAlignmentType.Centrato;
            ImageScaleLabelAsixX = 1;
            Visible = true;
            Color = ColorPDF.Nero;
        }

        public PointMarker Marker { get; set; }
        private float _fontsizelabelaxisx = 7;
        private float _fontsizelabelaxisy = 7;
        private Font _font = new Font("Verdana", 5.5f);
        private ColorPDF _fontcolorlabelaxisx = ColorPDF.Nero;
        private ColorPDF _fontcolorlabelaxisy = ColorPDF.Nero;
        private bool _fontboldlabelaxisy = true;

        public string ID { get; set; }

        /// <summary>
        /// Imposta o recupera un bool che indica se il Point sarà renderizzato sul grafico.
        /// Di default= true.
        /// </summary>
        public bool Visible { get; set; }

        /// <summary>
        /// Allineamento verticale del testo sulla barra.
        /// Di default = VerticalAlignmentType.Centrato.
        /// </summary>
        public VerticalAlignmentType VerticalAlignment { get; set; }

        /// <summary>
        /// Etichetta sull'asse Y
        /// </summary>
        public string LabelAxisY { get; set; }

        /// <summary>
        /// Etichetta sull'asse X
        /// </summary>
        public string LabelAxisX { get; set; }

        /// <summary>
        /// Imposta o recupera l'etichetta del point all'interno del grafico.
        /// </summary>
        public string Label { get; set; }

        /// <summary>
        /// Imposta o recupera il percorso dell'immagine da affiancare a sinistra della LabelAxisX.
        /// Di default = string.empty (non viene renderizzzata).
        /// </summary>
        public string ImagePathLabelAsixX { get; set; }

        /// <summary>
        /// Imposta o recupera il DeltaX dell'immagine da affiancare a sinistra della LabelAxisX.
        /// </summary>
        public float ImageDeltaXLabelAsixX { get; set; }

        /// <summary>
        /// Imposta o recupera la scala dell'immagine definita in ImagePathLabelAsixX.
        /// Di default=1.
        /// </summary>
        public float ImageScaleLabelAsixX { get; set; }

        /// <summary>
        /// Colore del point
        /// </summary>
        public ColorPDF Color { get; set; }

        /// <summary>
        /// Valore del Point
        /// </summary>
        /// <remarks>Utilizzare per i Chart che lavorano con la sola Y (ad esempio: Pie e Stacked)</remarks>
        public double Value { get; set; }

        /// <summary>
        /// Valori X e Y del Point. 
        /// </summary>
        /// <remarks>Utilizzare per i Chart che lavorano con X e Y (ad esempio: CombinationChart)</remarks>
        public ValuesPointXY Values { get; set; }

        /// <summary>
        /// bool che indica se mostrare la label sull'asse Y
        /// </summary>
        public bool ShowLabelAxisY { get; set; }

        /// <summary>
        /// bool che indica se mostrare la label sull'asse X
        /// </summary>
        public bool ShowLabelAxisX { get; set; }

        /// <summary>
        /// Imposta o recupera la dimensione del Font del Point sull'asse X.
        /// Di default = 7.
        /// </summary>
        public float FontSizeLabelAxisX
        {
            get { return _fontsizelabelaxisx; }
            set { _fontsizelabelaxisx = value; }
        }

        /// <summary>
        /// Imposta o recupera la dimensione del Font del Point sull'asse Y.
        /// Di default = 7.
        /// </summary>
        public float FontSizeLabelAxisY
        {
            get { return _fontsizelabelaxisy; }
            set { _fontsizelabelaxisy = value; }
        }
        public Font Font
        {
            get { return _font; }
            set { _font = value; }
        }

        /// <summary>
        /// Imposta o recupera il colore del Font del Point sull'asse X.
        /// Di default = Nero.
        /// </summary>
        public ColorPDF FontColorLabelAxisX
        {
            get { return _fontcolorlabelaxisx; }
            set { _fontcolorlabelaxisx = value; }
        }

        /// <summary>
        /// Imposta o recupera il colore del Font del Point sull'asse Y.
        /// Di default = Nero.
        /// </summary>
        public ColorPDF FontColorLabelAxisY
        {
            get { return _fontcolorlabelaxisy; }
            set { _fontcolorlabelaxisy = value; }
        }

        /// <summary>
        /// Imposta o recupera un bool che indica il Font grassetto del Point sull'asse X.
        /// Di default = false.
        /// </summary>
        public bool FontBoldLabelAxisX { get; set; }

        /// <summary>
        /// Imposta o recupera un bool che indica il Font grassetto del Point sull'asse Y.
        /// Di default = true.
        /// </summary>
        public bool FontBoldLabelAxisY
        {
            get { return _fontboldlabelaxisy; }
            set { _fontboldlabelaxisy = value; }
        }
    }

    public class PointMarker
    {
        public MarkerStyle MarkerStyle { get; set; }
        public float MarkerSize { get; set; }
        public Color MarkerColor { get; set; }
    }

    /// <summary>
    /// Rappresenta una struttura di X e Y da associare al Point di un ChartPDF.
    /// </summary>
    public class ValuesPointXY
    {
        public double X { get; set; }
        public double Y { get; set; }

        public Font font { get; set; }
        public ValuesPointXY(double x, double y, Font _font)
        {
            X = x;
            Y = y;
            font = _font;


        }

        public ValuesPointXY(double x, double y)
        {
            X = x;
            Y = y;



        }

    }

    public class Marker
    {
        public Marker()
        {
            Scale = 1;
        }
        public string Image { get; set; }
        public float Width { get; set; }
        public float Height { get; set; }
        public float X { get; set; }
        public float Y { get; set; }
        public float Scale { get; set; }
    }
}
