using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace MapClient
{    
    // this class is responsible for handling main application window
    public partial class MainWindow : Form
    {
        // variables using for drag'n'drop, zoom, etc
        private int cropX;
        private int cropY;
        private int width;
        private int height;
        private int beginResizeY;

        // during zooming we changes image, so we need to remember unchained one
        private Image unchangedImage;

        // the only one constructor
        public MainWindow(SimpleMapClient simpleMapClient)
        {
            this.simpleMapClient = simpleMapClient;
            InitializeComponent();
        }

        // these methods below are invoked when one of windows buttons is clicked
        private void refreshButton_Click(object sender, EventArgs e)
        {
            simpleMapClient.refreshMap();
        }

        private void schowSearched_Click(object sender, EventArgs e)
        {
            simpleMapClient.goToSelectedCity();
        }

        private void schowSerchedStreet_Click(object sender, EventArgs e)
        {
            simpleMapClient.goToSelectedStreet();
        }

        private void searchButton_Click(object sender, EventArgs e)
        {
            simpleMapClient.searchCity();
        }

        private void showMessagesButton_Click(object sender, EventArgs e)
        {
            simpleMapClient.showHelloWindow();
        }

        private void clearSelectedItemButton_Click(object sender, EventArgs e)
        {
            simpleMapClient.clearMapFromSearchedObject();
        }

        private void openFileButton_Click(object senderm, EventArgs e)
        {
            simpleMapClient.openFile();
        }

        // these two methods are called when drag'n'drop is changed between zomm and move
        private void zoomCheckedChanged(object sender, EventArgs e)
        {
            if(radioButton2.Checked)                                                                    // TODO: radioButton1,2 to kiepskie nazwy
                pictureBox1.Cursor = Cursors.Cross;
        }
        
        private void moveCheckedChanged(object sender, EventArgs e)
        {
            if(MoveOrZoomRadioButton.Checked)
                pictureBox1.Cursor = Cursors.Hand;
        }

        // this method is used for storing coordinates of place where mouse where clicked
        private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
        {
            // left mouse button: used for picture moving or zooming into
            // we'll change picture, so we need to remeber original
            if (e.Button == MouseButtons.Left)
            {
                cropX = e.X;
                cropY = e.Y;
                unchangedImage = pictureBox1.Image;
            }   // right mouse button: zoom in/out
            else if (e.Button == MouseButtons.Right)
            {
                beginResizeY = e.Y;
                unchangedImage = pictureBox1.Image;
            }
        }

        // this method handles processing of map image due to zoom or drag'n'drop
        private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
        {
            // right button: zoom in/out
            if (e.Button == MouseButtons.Right)
            {
                // size of a new map picture is based on distance between point of mouse down and current point
                                                                                    
                float factor = 1.0f + (float)(beginResizeY - e.Y) / (float)(getDisplayPanelHeight() / 2);
                int nWidth = (int)((float)getDisplayPanelWidth() * factor);        
                int nHeight = (int)((float)getDisplayPanelHeight() * factor);
                if (nWidth > 1 && nHeight > 1)
                {
                    Bitmap newImage = new Bitmap(nWidth, nHeight);
                    Graphics g = Graphics.FromImage((Image)newImage);
                    g.DrawImage(unchangedImage, 0, 0, nWidth, nHeight);
                    // after size calculations, new image is ready to be seen
                    pictureBox1.Image = newImage;
                }

            }
            else if (e.Button == MouseButtons.Left)
            {
                // left button is used for dragging map and zooming into selectted rectangle
                if (MoveOrZoomRadioButton.Checked)                                                                   
                {
                    // map dragging
                    int width = unchangedImage.Width;
                    int height = unchangedImage.Height;
                    Bitmap newImage = new Bitmap(width, height);
                    Graphics g = Graphics.FromImage((Image)newImage);
                    int x = e.X - cropX;
                    int y = e.Y - cropY;
                    g.DrawImage(unchangedImage, x, y, width, height);
                    pictureBox1.Image = newImage;
                }
                else
                {
                    // in this state one can see a rectangle drawn onto map. This rectangle selects the part of map to be zoomed into
                    width = e.X - cropX;
                    height = e.Y - cropY;

                    Pen pen = new Pen(Color.Red, 1);
                    Graphics g = Graphics.FromHwnd(pictureBox1.Handle);
                    // removing previous rectangle
                    this.pictureBox1.Refresh();

                    // rectangle don't have to be drawn from top left to bottom right corner; x,y values are always coordinates of top left corner
                    int newX, newY;
                    int newWidth, newHeight;

                    if (width < 0)
                    {
                        newX = cropX + width;
                        newWidth = -width;
                    }
                    else
                    {
                        newX = cropX;
                        newWidth = width;
                    }

                    if (height < 0)
                    {
                        newY = cropY + height;
                        newHeight = -height;
                    }
                    else
                    {
                        newY = cropY;
                        newHeight = height;
                    }
                    // drawing new rectangle
                    g.DrawRectangle(pen, new Rectangle(newX, newY, newWidth, newHeight));
                }
            }
           
        }

        // this method is invoked when mouse button is released; in most cases it results in map reloading
        private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
            {
                // right button: zoom in/out
                // we need to do some calculations to find new map size and position due to map size changes
                
                float factor = 1.0f + (float)(beginResizeY - e.Y) / (float)(getDisplayPanelHeight() / 2);
                float nWidth = ((float)getDisplayPanelWidth()) * factor;
                float nHeight =((float)getDisplayPanelHeight()) * factor;
                float x = (nWidth - ((float)getDisplayPanelWidth())) / (2.0f*factor);
                float y = (nHeight - ((float)getDisplayPanelHeight())) / (2.0f * factor);
                float width = ((float)getDisplayPanelWidth()) / factor;
                float height = ((float)getDisplayPanelHeight()) / factor;
                // this method download new map
                simpleMapClient.zoomTo((int)x, (int)y, (int)width, (int)height);
            }
            else if (e.Button == MouseButtons.Left)
            {
                // left button is used for dragging map and zooming into selectted rectangle

                if (MoveOrZoomRadioButton.Checked)
                {
                    // map dragging
                    int x = cropX - e.X + getDisplayPanelWidth() / 2;
                    int y = cropY - e.Y + getDisplayPanelHeight() / 2;
                    // downloads map with new position of center point
                    simpleMapClient.centerAt(x, y);
                }
                else
                {
                    // zooming into previously selected rectangle
                    // correcting values of width, heigt and position of top left corner
                    int newX, newY;
                    int newWidth, newHeight;

                    width = e.X - cropX;
                    height = e.Y - cropY;
                    if (width < 0)
                    {
                        newX = cropX + width;
                        newWidth = -width;
                    }
                    else
                    {
                        newX = cropX;
                        newWidth = width;
                    }

                    if (height < 0)
                    {
                        newY = cropY + height;
                        newHeight = -height;
                    }
                    else
                    {
                        newY = cropY;
                        newHeight = height;
                    }

                    // if selected rectangle was vey small, we only center map at selected point
                    if (newHeight < 3 || newWidth < 3)
                    {
                        simpleMapClient.centerAt(newX + newWidth / 2, newY + newHeight / 2);
                    }
                    else
                    {
                        simpleMapClient.zoomTo(newX, newY, newWidth, newHeight);
                    }
                } 
                
            }
        }

        // this method is call when an item from openFileGridView is selected           
        private void openFiledataGrid_Click(object sender, EventArgs e)
        {
            simpleMapClient.goToLocationSelectedInGrid(getCurrentRowIndex());
        }



        // this is method is invoked during window closing
        private void MainWindow_FormClosed(object sender, FormClosedEventArgs e)
        {
            simpleMapClient.closeSOAPConnection();
            Application.Exit();
        }

    }
}