// The MIT License (MIT)
// Copyright (c) 2014 Nicolas Kogler

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.

using System;
using System.Text;
using System.Drawing;
using System.Collections;
using System.Windows.Forms;
using System.ComponentModel;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;

namespace IMLibrary.Controls.Win8form
{
    sealed class SharpMenu : ContextMenuStrip
    {
        #region Variables

        private Form parent;
        private ToolStripMenuItem restore;
        private ToolStripMenuItem close;
        private ToolStripMenuItem move;

        private ToolStripMenuItem size;
        private ToolStripMenuItem mini;
        private ToolStripMenuItem maxi;
        private ToolStripSeparator sepa;

        public event SharpMenuEventHandler SysEvent;

        #endregion

        #region Constructor

        /// <summary>
        /// Programmatically constructs our full system-contextmenu
        /// and adds eventhandlers and shortcuts to them.
        /// Modify this to implement your own functions.
        /// </summary>
        public SharpMenu(Form parent) : base()
        {
            this.parent = parent;
            this.DoubleBuffered = true;
            this.Renderer = new SharpMenuRenderer();

            this.restore = new ToolStripMenuItem(Resources.Restore);
            this.move = new ToolStripMenuItem(Resources.Move);
            this.size = new ToolStripMenuItem(Resources.Size );
            this.mini = new ToolStripMenuItem(Resources.Minimizes);
            this.maxi = new ToolStripMenuItem(Resources.Maximizes);
            this.close = new ToolStripMenuItem(Resources.Closes);
            this.sepa = new ToolStripSeparator();

            this.move.Click += OnSharpMenuClick;
            this.size.Click += OnSharpMenuClick;
            this.mini.Click += OnSharpMenuClick;
            this.maxi.Click += OnSharpMenuClick;
            this.close.Click += OnSharpMenuClick;
            this.restore.Click += OnSharpMenuClick;

            this.close.ShortcutKeys = (Keys.Alt | Keys.F4);
            this.Items.AddRange(new ToolStripItem[] { 
                restore, move, size, mini, maxi, sepa, close });
        }

        #endregion

        #region Functioning

        /// <summary>
        /// We receive the formwindowstate to disable
        /// certain menuitems so they cannot be accessed
        /// by the user. If you added your own menuitem,
        /// you have to handle its enability as well.
        /// </summary>
        protected override void OnOpened(EventArgs e)
        {
            switch (this.parent.WindowState)
            {
                case FormWindowState.Normal:
                    this.restore.Enabled = false;
                    this.maxi.Enabled = true;
                    this.mini.Enabled = true;
                    this.move.Enabled = true;
                    this.size.Enabled = true;
                    break;
                case FormWindowState.Minimized:
                    this.restore.Enabled = true;
                    this.maxi.Enabled = true;
                    this.mini.Enabled = false;
                    this.move.Enabled = false;
                    this.size.Enabled = false;
                    break;
                case FormWindowState.Maximized:
                    this.restore.Enabled = true;
                    this.mini.Enabled = true;
                    this.maxi.Enabled = false;
                    this.move.Enabled = false;
                    this.size.Enabled = false;
                    break;
            }

            base.OnOpened(e);
        }

        /// <summary>
        /// Receives the index of the clicked menuitem
        /// and sends messages to WndProc. If you implemented
        /// your own item, you might modify the switch too.
        /// </summary>
        private void OnSharpMenuClick(object obj, EventArgs e)
        {
            switch (this.Items.IndexOf((ToolStripMenuItem)obj))
            {
                case 0:
                    SendSystemCmd(SharpHelper.SystemCmd.CMD_RESTORE);
                    break;
                case 1:
                    SendSystemCmd(SharpHelper.SystemCmd.CMD_MOVE);
                    break;
                case 2:
                    SendSystemCmd(SharpHelper.SystemCmd.CMD_SIZE);
                    break;
                case 3:
                    SendSystemCmd(SharpHelper.SystemCmd.CMD_MINI);
                    break;
                case 4:
                    SendSystemCmd(SharpHelper.SystemCmd.CMD_MAXI);
                    break;
                case 6:
                    SendSystemCmd(SharpHelper.SystemCmd.CMD_CLOSE);
                    break;
            }
        }

        /// <summary>
        /// Creates eventargs from the message and
        /// fires an event for our custom form.
        /// </summary>
        private void SendSystemCmd(SharpHelper.SystemCmd cmd)
        {
            if (this.SysEvent != null)
            {
                var arg = new SharpMenuEventArgs((int)cmd);
                this.SysEvent(this, arg);
            }
        }

        #endregion
    }

    public class SharpMenuEventArgs : EventArgs
    {
        #region Variables

        private int cmd;

        public int Command
        {
            get
            {
                return cmd;
            }
        }

        #endregion

        #region Constructor

        public SharpMenuEventArgs(int cmd)
        {
            this.cmd = cmd;
        }

        #endregion
    }

    /// <summary>
    /// The eventhandler that is used to send messages
    /// to its event (and finally sending it to WndProc after).
    /// If you want to implement complex functions, you might
    /// want to modify the SharpMenuEventArgs.
    /// </summary>
    public delegate void SharpMenuEventHandler(object obj, SharpMenuEventArgs arg);
}