// Chattr - Twitter client on .NET
//
// Copyright (c) 2007, 2008 Katsuhiko Ichinose <ichi@users.sourceforge.jp>
//
// Chattr is Free Software released under GNU General Public License.
//
// $Id: FormPopup.cs 208 2009-08-16 07:27:51Z ichi $

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

using System.Diagnostics;
using System.Collections;

namespace Chattr
{
    public partial class FormPopup : Form
    {
        private enum State
        {
            IDLE,
            FADE_IN,
            DISPLAY,
            FADE_OUT
        }
        private const double FADE_IN = 500;
        private const double FADE_OUT = 1000;
        private const double MAX_OPACITY = 0.99;

        private FormMain m_FormMain;
        private FormPost m_FormPost;
        private State m_State = State.IDLE;
        private DateTime m_Time;
        private LinkedList<IPopup> m_List = new LinkedList<IPopup>();
        private IPopup m_IPopup;

        public FormPopup(FormMain formMain, FormPost formPost)
        {
            InitializeComponent();
            m_FormMain = formMain;
            m_FormPost = formPost;
            m_State = State.IDLE;
            this.Opacity = 0;
            this.Show();
        }

        protected override void OnPaintBackground(PaintEventArgs pevent)
        {
        }

        public void Add(long id, int flags, string user, string text)
        {
            m_List.AddLast(new IPopup(id, flags, user, text));
            AddItem();
        }

        private void AddItem()
        {
            if (m_List.Count > 0)
            {
                int cnt = listBoxStatuses.Items.Count;
                listBoxStatuses.BeginUpdate();
                while (m_List.Count > 0)
                {
                    IPopup popup = m_List.First.Value;
                    listBoxStatuses.Items.Add(popup);
                    ChangeLocation();
                    if (this.Location.Y >= 0)
                    {
                        m_List.RemoveFirst();
                    }
                    else
                    {
                        listBoxStatuses.Items.RemoveAt(listBoxStatuses.Items.Count - 1);
                        ChangeLocation();
                        break;
                    }
                }
                listBoxStatuses.EndUpdate();
                if (cnt == 0)
                {
                    FadeIn();
                }
                else
                {
                    Display(listBoxStatuses.Items.Count - cnt);
                }
                Debug.WriteLine("AddItem: " + this.Location + " / " + this.Height);
            }
        }

        private int MeasureHeight()
        {
            int height = 0;
            for (int i = 0; i < listBoxStatuses.Items.Count; i++)
            {
                height += listBoxStatuses.GetItemHeight(i);
            }
            return height;
        }

        private void ChangeLocation()
        {
            int height = MeasureHeight();
            Rectangle rect = Screen.PrimaryScreen.Bounds;
            int workHeight = Screen.GetWorkingArea(new Point(0, 0)).Height;
            int postHeight = 0;
            if (m_FormPost.Visible)
            {
                postHeight = m_FormPost.Height;
            }
            int side = 0;
            if (Properties.Settings.Default.PopupSideBar)
            {
                side += 150;
            }
            int h = 8;
            if (Environment.OSVersion.Version.Major > 5)
            {
                h = 7;
            }
            this.Location = new Point(rect.Width - this.Width - side, workHeight - postHeight - height - h);
            this.Height = height + h;
        }

        private void Idle()
        {
            m_State = State.IDLE;
            this.Opacity = 0;
            timer.Enabled = false;
            listBoxStatuses.Items.Clear();
            AddItem();
        }

        private void FadeIn()
        {
            m_State = State.FADE_IN;
            m_Time = DateTime.Now;
            timer.Interval = 100;
            timer.Enabled = true;
        }

        private void FadeOut()
        {
            m_State = State.FADE_OUT;
            m_Time = DateTime.Now;
            timer.Enabled = false;
            timer.Interval = 100;
            timer.Enabled = true;
        }

        private void Display(int count)
        {
            m_State = State.DISPLAY;
            this.Opacity = MAX_OPACITY;
            timer.Enabled = false;
            timer.Interval = 3000 + (1000 * (count - 1));
            timer.Enabled = true;
        }

        private void ReDisplay()
        {
            m_State = State.DISPLAY;
            this.Opacity = MAX_OPACITY;
            timer.Enabled = false;
            timer.Interval = 500;
            timer.Enabled = true;
        }

        private void FormPopup_Load(object sender, EventArgs e)
        {
            Rectangle rect = Screen.PrimaryScreen.Bounds;
            int workHeight = Screen.GetWorkingArea(new Point(0, 0)).Height;
            this.Location = new Point(rect.Width - this.Width, workHeight - this.Height);
        }

        private void listBoxStatuses_MeasureItem(object sender, MeasureItemEventArgs e)
        {
            IPopup popup = listBoxStatuses.Items[e.Index] as IPopup;
            int width = listBoxStatuses.Width - 4;
            Font font = new Font(listBoxStatuses.Font.FontFamily, listBoxStatuses.Font.Size, FontStyle.Bold);
            SizeF u = e.Graphics.MeasureString(popup.User, font, width - 2);
            SizeF t = e.Graphics.MeasureString(popup.Text + "\n", listBoxStatuses.Font, width - 2);
            e.ItemHeight = (int)(u.Height + t.Height + 0.5) + 5;
            if (e.ItemHeight > 255)
            {
                e.ItemHeight = 255;
            }
        }

        private void listBoxStatuses_DrawItem(object sender, DrawItemEventArgs e)
        {
            if ((e.Index >= 0) && (e.Index < listBoxStatuses.Items.Count))
            {
                IPopup popup = listBoxStatuses.Items[e.Index] as IPopup;
                // Brush
                Brush brushText;
                Brush brushBg;
                if (!Properties.Settings.Default.PopupColor)
                {
                    brushText = new SolidBrush(ForeColor);
                    brushBg = new SolidBrush(BackColor);
                }
                else if ((popup.Flags & FormMain.FLAG_INME) != 0)
                {
                    brushText = new SolidBrush(Properties.Settings.Default.ColorInMe);
                    brushBg = new SolidBrush(Properties.Settings.Default.BgColorInMe);
                }
                else if ((popup.Flags & FormMain.FLAG_KEYWORDS) != 0)
                {
                    brushText = new SolidBrush(Properties.Settings.Default.ColorKeywords);
                    brushBg = new SolidBrush(Properties.Settings.Default.BgColorKeywords);
                }
                else
                {
                    brushText = new SolidBrush(Properties.Settings.Default.ColorText);
                    brushBg = new SolidBrush(Properties.Settings.Default.BgColor);
                }
                Font font = new Font(listBoxStatuses.Font.FontFamily, listBoxStatuses.Font.Size, FontStyle.Bold);
                SizeF u = e.Graphics.MeasureString(popup.User, font, e.Bounds.Width - 2);
                RectangleF rect = new RectangleF(1, e.Bounds.Top + 1, e.Bounds.Width - 2, Bounds.Height - 1);
                e.Graphics.FillRectangle(brushBg, e.Bounds);
                e.Graphics.DrawString(popup.User, font, brushText, rect);
                rect = new RectangleF(1, e.Bounds.Top + u.Height + 1, e.Bounds.Width - 2, Bounds.Height - u.Height - 1);
                e.Graphics.DrawString(popup.Text, listBoxStatuses.Font, brushText, rect);
            }
        }

        private void timer_Tick(object sender, EventArgs e)
        {
            DateTime now = DateTime.Now;
            TimeSpan span = now - m_Time;
            switch ((int)m_State)
            {
                case (int)State.DISPLAY:
                    if (listBoxStatuses.Bounds.Contains(this.PointToClient(MousePosition)))
                    {
                        ReDisplay();
                    }
                    else
                    {
                        FadeOut();
                    }
                    break;
                case (int)State.FADE_IN:
                    if (span.TotalMilliseconds >= FADE_IN)
                    {
                        Display(listBoxStatuses.Items.Count);
                    }
                    else
                    {
                        double opacity = span.TotalMilliseconds / FADE_IN;
                        if (opacity >= 1.0)
                        {
                            opacity = MAX_OPACITY;
                        }
                        this.Opacity = opacity;
                    }
                    break;
                case (int)State.FADE_OUT:
                    if (listBoxStatuses.Bounds.Contains(this.PointToClient(MousePosition)))
                    {
                        ReDisplay();
                    }
                    else if (span.TotalMilliseconds >= FADE_OUT)
                    {
                        Idle();
                    }
                    else
                    {
                        double opacity = 1.0 - (span.TotalMilliseconds / FADE_OUT);
                        if (opacity >= 1.0)
                        {
                            opacity = MAX_OPACITY;
                        }
                        this.Opacity = opacity;
                    }
                    break;
            }
        }

        private void contextMenuStrip_Opening(object sender, CancelEventArgs e)
        {
            if ((listBoxStatuses.SelectedIndex >= 0) && (listBoxStatuses.SelectedIndex < listBoxStatuses.Items.Count))
            {
                IPopup popup = listBoxStatuses.Items[listBoxStatuses.SelectedIndex] as IPopup;
                if (popup != null)
                {
                    m_IPopup = new IPopup(popup.ID, popup.Flags, popup.User, popup.Text);
                    m_FormMain.PostContextMenuStripMake(contextMenuStrip, m_IPopup.ID);
                }
            }
            else
            {
                e.Cancel = true;
                m_IPopup = null;
            }
        }

        private void listBoxStatuses_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
            {
                int idx = listBoxStatuses.IndexFromPoint(e.Location);
                if (idx != ListBox.NoMatches)
                {
                    listBoxStatuses.SelectedIndex = idx;
                }
                else
                {
                    listBoxStatuses.SelectedIndex = -1;
                }
            }
        }

        private void toolStripMenuItemReply_Click(object sender, EventArgs e)
        {
            if (m_IPopup != null)
            {
                m_FormMain.PostReply(m_IPopup.ID);
            }
        }

        private void toolStripMenuItemDirect_Click(object sender, EventArgs e)
        {
            if (m_IPopup != null)
            {
                m_FormMain.PostDirectMessage(m_IPopup.ID);
            }
        }

        private void toolStripMenuItemFavorite_Click(object sender, EventArgs e)
        {
            if (m_IPopup != null)
            {
                m_FormMain.PostFavorite(m_IPopup.ID);
            }
        }

        private void toolStripMenuItemReblog_Click(object sender, EventArgs e)
        {
            if (m_IPopup != null)
            {
                m_FormMain.PostReblog(m_IPopup.ID);
            }
        }

        private void toolStripMenuItemReTweet_Click(object sender, EventArgs e)
        {
            if (m_IPopup != null)
            {
                m_FormMain.PostReTweet(m_IPopup.ID);
            }
        }
    }
}