// Created with MonoDevelop
//
//    Copyright (C) 2010 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.Drawing;


namespace Hiperscan.NPlotEngine
{

    public class RubberBandSelection
    {
        private readonly IPlotEngine plot;
        private int width, height;

        public event EventHandler<EventArgs> Changed;
        
        
        public RubberBandSelection(IPlotEngine p, int x, int y, int width, int height)
        {
            this.plot = p;
            this.XStart = x;
            this.YStart = y;
            this.width  = width;
            this.height = height;
            this.Update();
        }
        
        private void Update()
        {
            try
            {
                int x_min = this.plot.PhysicalXMin;
                int x_max = this.plot.PhysicalXMax;
                int y_min = this.plot.PhysicalYMax;
                int y_max = this.plot.PhysicalYMin;
            
                if (this.width >= 0)
                {
                    X = this.XStart;
                    this.Width = this.width;
                }
                else
                {
                    X = this.XStart + this.width;
                    this.Width = -this.width;
                }
            
                if (this.height >= 0)
                {
                    Y = this.YStart;
                    this.Height = this.height;
                }
                else
                {
                    Y = this.YStart + this.height;
                    this.Height = -this.height;
                }
            
                // crop to diagram size
                if (X < x_min)
                {
                    this.Width = this.Width - x_min + X;
                    X = x_min;
                }
                if (X > x_max) X = x_max;
                if (X + this.Width > x_max) this.Width = x_max- X; 
            
                if (Y < y_min)
                {
                    this.Height = this.Height - y_min + Y;
                    Y = y_min;
                }
                if (Y > y_max) Y = y_max;
                if (Y + this.Height > y_max) this.Height = y_max- Y; 
            }
            catch (NullReferenceException ex)
            {
                // may happen if plot is changed asynchronously
                Console.WriteLine("Exception in RubberBandSelection.Update(): " + ex.ToString());
            }
        }
        
        public void Draw(Graphics g)
        {
            Rectangle r = new Rectangle(this.X, this.Y, this.Width, this.Height);
            Brush b = new SolidBrush(Color.FromArgb(50, Color.Blue));
            g.FillRectangle(b, r);
        }
        
        public void SetSize(int width, int height)
        {
            this.width  = width;
            this.height = height;
            this.Update();

            this.Changed?.Invoke(this, EventArgs.Empty);
        }

        public void SetPosition(int x, int y)
        {
            this.XStart = x;
            this.YStart = y;
            this.Update();

            this.Changed?.Invoke(this, EventArgs.Empty);
        }

        public int X         { get; private set; }
        public int Y         { get; private set; }
        public int XStart    { get; private set; }
        public int YStart    { get; private set; }
        public int Width     { get; private set; }
        public int Height    { get; private set; }

        public bool IsStatic { get; set; } = false;
    }
}