using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
using System.Diagnostics;
using XWolf.Aero;
using System.Drawing.Imaging;
using System.IO;

namespace Launcheroid
{
    public partial class Form1 : XGlassForm
    {
        private const int iconSize = 48;//128;
        private const int iconX = (tileW - iconSize) / 2;
        private const int iconY = 10;
        private const int tileW = 120;
        private const int tileH = 90;
        private static IntPtr HTCAPTION = (IntPtr)2;
        private static Brush selBrush = new SolidBrush(Color.FromArgb(170, SystemColors.Highlight));
        private static Pen scrollPen = new Pen(SystemColors.ControlDarkDark);

        private int cols;
        private int rows;
        private lLink[] links;
        private Point mPoint;
        private lLink selected;
        private bool inside = false;
        private int scrollindex = 0, scrollheight = -1, scrollbarh = 0;
        private bool navigate = false;
        private Launcher launcher=new Launcher();
        private string path;

        protected override void WndProc(ref Message message)
        {
            const int WM_NCHITTEST = 0x0084;
            base.WndProc(ref message);
            if (message.Msg == WM_NCHITTEST)
            {
                int r = message.Result.ToInt32();
                if (r >= 10 && r <= 18)
                    message.Result = HTCAPTION;
            }
        }

        public Form1(string path)
        {
            InitializeComponent();
            this.path = path;
            if (path != null)
            {
                if (File.Exists(path))
                    launcher.Load(path);
                else if (navigate = Directory.Exists(path))
                    launcher.Navigate(path);
                else throw new Exception("La ruta " + path + " no existe");

            }
            else launcher.Load(null);
            if (navigate)
            {
                AllowDrop = false;
                ContextMenuStrip = navMenuStrip;
            }
            MouseWheel += new MouseEventHandler(Form1_MouseWheel);
            if (Glass.Composite)
                FullGlass = true;
            else
                FormBorderStyle = FormBorderStyle.None;
        }

        #region NO AERO

        private Bitmap GetNoaeroBG()
        {
            Point zeropoint = new Point(0, 0);
            Point pos = PointToScreen(zeropoint);
            Size sz = ClientSize;
            Bitmap capture = new Bitmap(sz.Width, sz.Height);
            using (Graphics g = Graphics.FromImage(capture))
            {
                g.CopyFromScreen(pos, zeropoint, sz);
            }
            Bitmap capture2 = new Bitmap(sz.Width / 2, sz.Height / 2);
            using (Graphics g = Graphics.FromImage(capture2))
            {
                g.InterpolationMode = InterpolationMode.HighQualityBilinear;
                g.SmoothingMode = SmoothingMode.HighQuality;
                g.DrawImage(capture, 0, 0, sz.Width / 2, sz.Height / 2);
            }
            capture.Dispose();
            Bitmap noaerobg = new Bitmap(sz.Width, sz.Height);
            using (Graphics g = Graphics.FromImage(noaerobg))
            {
                ColorMatrix matrix = new ColorMatrix();
                matrix.Matrix33 = 0.8f; //opacity 0 = completely transparent, 1 = completely opaque
                ImageAttributes attr = new ImageAttributes();
                attr.SetColorMatrix(matrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);

                g.InterpolationMode = InterpolationMode.HighQualityBilinear;
                g.SmoothingMode = SmoothingMode.HighQuality;
                g.DrawImage(capture2, new Rectangle(0, 0, sz.Width, sz.Height), 0, 0, sz.Width / 2, sz.Height / 2, GraphicsUnit.Pixel, attr);
            }
            capture2.Dispose();
            return noaerobg;
        }

        #endregion

        private void ReAlign()
        {
            links = launcher.Links;
            Size screensize=Screen.FromControl(this).WorkingArea.Size;
            int maxcols = screensize.Width / tileW;
            if (links.Length <= 1)
            {
                cols = 1;
                rows = 1;
            }
            else
                if (links.Length == 2)
                {
                    cols = 2;
                    rows = 1;
                }
                else
                {
                    cols = (int)Math.Ceiling(Math.Sqrt(links.Length)) + 1;
                    if (cols * tileW > screensize.Width)
                        cols = maxcols;
                    rows = links.Length / cols;
                    if (links.Length % cols > 0)
                        rows++;
                }
            Size cs = new Size(cols * tileW, rows * tileH);
            if (cs.Height > screensize.Height)
                if (cols < maxcols)
                {
                    cols = maxcols;
                    rows = links.Length / cols;
                    cs = new Size(cols * tileW, rows * tileH);
                }
            if (cs.Height > screensize.Height)
            {
                cols = maxcols;
                rows = links.Length / cols;
                if (links.Length % cols > 0)
                    rows++;
                scrollheight = (rows * tileH) + 10;
                cs = new Size((cols * tileW) + 25, screensize.Height - 75);
                scrollbarh = scrollheight - cs.Height;
                if (scrollindex > scrollbarh)
                    scrollindex = scrollbarh;
            }
            else
                scrollheight = -1;
            ClientSize = cs;
            if (Top + Height + 10 > screensize.Height)
                Top = screensize.Height - (Height + 10);
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            ReAlign();
            int left = Cursor.Position.X - Width / 2;
            int top = Cursor.Position.Y - Height / 2;
            if (top < 10)
                top = 10;
            if (top + Height >  Screen.PrimaryScreen.WorkingArea.Height - 10)
                top = Screen.PrimaryScreen.WorkingArea.Height - (10 + Height);
            Top = top;
            if (left < 10)
                left = 10;
            if (left + Width > Screen.PrimaryScreen.WorkingArea.Width - 10)
                left = Screen.PrimaryScreen.WorkingArea.Width - (10 + Width);
            Left = left;
        }

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            Graphics g = e.Graphics;
            g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAliasGridFit;
            g.PixelOffsetMode = PixelOffsetMode.None;
            if (Glass.Composite)
                g.Clear(Color.Transparent);
            else
            {
                g.Clear(Color.SkyBlue);
                Bitmap bg = GetNoaeroBG();
                if (bg != null)
                    g.DrawImage(bg, ClientRectangle);
            }
            int x = 0, y = 0;
            int select = -1;
            int index = 0;
            foreach (lLink lnk in links)
            {
                Image ico = lnk.Icon;
                if (ico == null)
                    ico = IconTool.GetDirectoryIcon();
                int px = (x * tileW);
                int py = (y * tileH);
                py -= scrollindex;
                bool sel = false;
                if (mPoint != null)
                    sel = ((mPoint.X > px) && (mPoint.X - tileW < px)) && ((mPoint.Y > py) && (mPoint.Y - tileH < py));
                if (sel)
                {
                    g.FillRectangle(selBrush, px, py, tileW, tileH);
                    select = index;
                }
                g.DrawImage(ico, px + iconX, py + iconY, iconSize, iconSize);
                GfxTools.DrawString(g, lnk.Name, px + tileW / 2, py + tileH - 24);
                x++;
                if (x >= cols)
                {
                    x = 0;
                    y++;
                }
                index++;
            }
            if (select == -1)
                selected = null;
            else
                selected = links[select];
            if (scrollheight > -1)
            {
                GfxTools.DrawRoundRect(g, scrollPen, ClientSize.Width - 11, 1, 10, ClientSize.Height - 2, 3);
                int sbh = (ClientSize.Height - 2) - scrollbarh;
                int sbi = scrollindex;
                if (sbh < 10)
                {
                    sbh = 10;
                    sbi = (sbi * (ClientSize.Height - 12)) / scrollbarh;
                }
                GfxTools.FillRoundRect(g, scrollPen.Brush, ClientSize.Width - 11, 1 + sbi, 10, sbh, 3);
            }
        }

        private void Form1_MouseWheel(object sender, MouseEventArgs e)
        {
            scrollindex -= e.Delta / 3;
            if (scrollindex < 0)
                scrollindex = 0;
            if (scrollindex > scrollbarh)
                scrollindex = scrollbarh;
            Invalidate();
        }

        private void Form1_Deactivate(object sender, EventArgs e)
        {
            if (!inside)
                t1.Enabled = true;
            else
                t1.Enabled = false;
        }

        private void Form1_KeyUp(object sender, KeyEventArgs e)
        {

        }

        private void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Escape)
                Close();
        }

        private void t1_Tick(object sender, EventArgs e)
        {
            Close();
        }

        private void Form1_Activated(object sender, EventArgs e)
        {
            t1.Enabled = false;
        }

        private void Form1_DragEnter(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop)) e.Effect = DragDropEffects.Copy;
        }

        private void Form1_DragDrop(object sender, DragEventArgs e)
        {
            string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
            if (files.Length == 0)
                return;
            foreach (string file in files)
                launcher.Add(file);
            launcher.Save();
            ReAlign();
            Update();
        }

        private void Form1_MouseMove(object sender, MouseEventArgs e)
        {
            mPoint = new Point(e.X, e.Y);
            Invalidate();
        }

        private void Form1_MouseClick(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Middle)
                Close();
            if (selected == null)
                return;
            inside = true;
            if (e.Button == MouseButtons.Left)
                if (selected.Navigate)
                {
                    inside = true;
                    Hide();
                    if (selected.Open())
                        DialogResult = DialogResult.OK;
                    else
                    {
                        Show();
                        Focus();
                        inside = false;
                    }
                }
                else if (selected.Open())
                    DialogResult = DialogResult.OK;
            inside = false;
        }

        private void formMenuStrip_Opening(object sender, CancelEventArgs e)
        {
            bool itemen = selected != null;
            borrarToolStripMenuItem.Enabled = itemen;
            propiedadesToolStripMenuItem.Enabled = itemen;
        }

        private void borrarToolStripMenuItem_Click(object sender, EventArgs e)
        {
            launcher.Del(selected);
            launcher.Save();
            ReAlign();
            Invalidate();
        }

        private void propiedadesToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (selected == null)
                return;
            inside = true;
            FItem.Execute(launcher, selected);
            inside = false;
            Focus();
            Invalidate();
        }

        private void abrirCarpetaContenedoraToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Process.Start(path);
            DialogResult = DialogResult.OK;
        }

        private void Form1_Shown(object sender, EventArgs e)
        {
            if (!Glass.Composite)
            {
                Opacity = 0.99;
                Timer updt = new Timer();
                updt.Tick += new EventHandler(updt_Tick);
                updt.Interval = 500;
                updt.Enabled = true;
            }
        }

        void updt_Tick(object sender, EventArgs e)
        {
            Invalidate();
        }

        private void navMenuStrip_Opening(object sender, CancelEventArgs e)
        {
            bool itemen = selected != null;
            abrirCarpetaToolStripMenuItem.Enabled = itemen;
        }

        private void abrirCarpetaToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Process.Start(selected.Path);
            DialogResult = DialogResult.OK;
        }
    }
}
