// Copyright(C) 2003 Daisuke Arai <darai@users.sourceforge.jp>
// Copyright(C) 2004-2008, 2010 panacoran <panacoran@users.sourceforge.jp>
// 
// This program is part of Protra.
//
// Protra 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/>.
// 
// $Id: MainForm.cs 393 2010-11-28 15:50:33Z panacoran $

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using Protra.Dialogs;
using Protra.Lib;
using Protra.Lib.Config;
using Protra.Lib.Data;
using Protra.Lib.Dialogs;

namespace Protra
{
    /// <summary>
    /// メインフォーム
    /// </summary>
    public partial class MainForm : Form
    {
        /// <summary>
        /// コンストラクタ
        /// </summary>
        public MainForm()
        {
            InitializeComponent();
            
            //設定ファイルの読み込み。
            (GlobalEnv.ProtraConfig = new ProtraConfig()).Load();
            (GlobalEnv.UpdateConfig = new UpdateConfig()).Load();
            (GlobalEnv.BrandData = new Protra.Lib.Data.BrandData()).Load();
            (GlobalEnv.BrandListConfig = new BrandListConfig()).Load();

            ChartPanelInit();
            if (GlobalEnv.ProtraConfig.ChartMode == 1)
                weeklyChartToolStripMenuItem.PerformClick();
            BrandListInit();
            foreach (var bl in GlobalEnv.BrandListConfig.List)
                if (GlobalEnv.ProtraConfig.BrandListName == bl.Name)
                {
                    comboBoxBrandList.SelectedItem = bl;
                    break;
                }
            foreach (var item in listBoxBrandList.Items)
                if (((Brand)item).Code == GlobalEnv.ProtraConfig.SelectedCode)
                {
                    listBoxBrandList.SelectedItem = item;
                    break;
                }
            GlobalEnv.BrandData.SetWatcher(BrandListInit);
            GlobalEnv.BrandListConfig.SetWatcher(BrandListInit);
            GlobalEnv.UpdateConfig.SetWatcher(null);
        }

        private void ChartPanelInit()
        {
            var p = GlobalEnv.ProtraConfig;
            chartPanel.HScrollBar = hScrollBarChart;
            chartPanel.ChartNum = p.ChartNum;
            chartPanel.ChartForeColor = Color.FromArgb(p.ChartForeColor);
            chartPanel.ChartBackColor = Color.FromArgb(p.ChartBackColor);
            chartPanel.UseDifferentChart = p.UseDifferentChart;
            chartPanel.DrawLastWeek = p.DrawLastWeek;

            for (int n = 0; n < p.ChartList.Count; n++)
            {
                ChartConfig c = p.ChartList[n];
                if (c.DailyFile != null)
                    chartPanel.ChartBoxes[n].DailyProgramFile =
                        Path.Combine(Global.DirChart, c.DailyFile);
                if (c.WeeklyFile != null)
                    chartPanel.ChartBoxes[n].WeeklyProgramFile =
                        Path.Combine(Global.DirChart, c.WeeklyFile);
            }
            chartPanel.SetPriceInfo = SetPriceInfo;
            var code = GlobalEnv.ProtraConfig.SelectedCode;
            if (code == null)
                return;
            chartPanel.SelectedCode = code;
            SetBrandInfo(GlobalEnv.BrandData[code]);
        }

        private void BrandListInit()
        {
            var item = (BrandList)comboBoxBrandList.SelectedItem;
            var brand = (Brand)listBoxBrandList.SelectedItem;
            SuspendLayout();
            comboBoxBrandList.Items.Clear();
            foreach (var bl in GlobalEnv.BrandListConfig.List)
            {
                comboBoxBrandList.Items.Add(bl);
                if (item != null && item.Name == bl.Name)
                {
                    comboBoxBrandList.SelectedItem = bl;
                    if (brand != null && bl.List.Contains(brand.Code))
                        listBoxBrandList.SelectedItem = GlobalEnv.BrandData[brand.Code];
                }
            }
            if (comboBoxBrandList.SelectedItem == null &&
                comboBoxBrandList.Items.Count > 0)
                comboBoxBrandList.SelectedIndex = 0;
            ResumeLayout();
        }

        /// <summary>
        /// メインエントリポイント
        /// </summary>
        [STAThread]
        public static void Main()
        {
            if (Win32API.ProcessAlreadyExists())
                return;
            Application.EnableVisualStyles();
            Application.Run(new MainForm());
        }


        private string StripChartDirName(string path)
        {
            if (path == null)
                return null;
            return path.Substring(Global.DirChart.Length + 1, path.Length - Global.DirChart.Length - 1);
        }

        private Rectangle normalBounds;

        /// <summary>
        /// 設定ファイルを書き込む。
        /// </summary>
        private void ConfigWrite()
        {
            // フォーム
            var p = GlobalEnv.ProtraConfig;
            p.Width = normalBounds.Width;
            p.Height = normalBounds.Height;
            p.Maximized = WindowState == FormWindowState.Maximized;
            p.PanelLeftWidth = splitContainerMain.SplitterDistance;
            var item = (BrandList)comboBoxBrandList.SelectedItem;
            p.BrandListName = item != null ? item.Name : null;
            // チャート
            p.SelectedCode = chartPanel.SelectedCode;
            p.ChartMode = dailyChartToolStripMenuItem.Checked ? 0 : 1;
            p.ChartNum = chartPanel.ChartNum;
            p.ChartForeColor = (chartPanel.ChartForeColor).ToArgb();
            p.ChartBackColor = chartPanel.ChartBackColor.ToArgb();
            p.ChartList.Clear();

            for (int i = 0; i < p.ChartNum; i++)
            {
                var chart = new ChartConfig();
                chart.DailyFile =
                    StripChartDirName(chartPanel.ChartBoxes[i].DailyProgramFile);
                chart.WeeklyFile =
                    StripChartDirName(chartPanel.ChartBoxes[i].WeeklyProgramFile);
                chart.Height = chartPanel.ChartBoxes[i].Height;
                p.ChartList.Add(chart);
            }
            p.Save();
        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            var p = GlobalEnv.ProtraConfig;
            if (p.Height == 0) // 設定ファイルが存在しない
            {
                normalBounds = Bounds;
                return;
            }
            Width = p.Width;
            Height = p.Height;
            normalBounds = Bounds;
            if (p.Maximized)
                WindowState = FormWindowState.Maximized;
            splitContainerMain.SplitterDistance = p.PanelLeftWidth;

            for (int i = 0; i < p.ChartNum; i++)
                chartPanel.ChartBoxes[i].Height = p.ChartList[i].Height;
        }

        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            ConfigWrite();
        }

        private void MainForm_LocationChanged(object sender, System.EventArgs e)
        {
            // 通常の状態なら位置を保存
            if (this.WindowState == FormWindowState.Normal)
                normalBounds = this.Bounds;
        }

        private void MainForm_SizeChanged(object sender, System.EventArgs e)
        {
            // 通常の状態ならサイズを保存
            if (this.WindowState == FormWindowState.Normal)
                normalBounds = this.Bounds;
        }

        private void dailyChartToolStripMenuItem_Click(object sender, EventArgs e)
        {
            weeklyChartToolStripMenuItem.Checked = false;
            dailyChartToolStripButton.Checked = true;
            weeklyChartToolStripButton.Checked = false;
            chartPanel.ChartMode = 0;
        }

        private void weeklyChartToolStripMenuItem_Click(object sender, EventArgs e)
        {
            dailyChartToolStripMenuItem.Checked = false;
            weeklyChartToolStripButton.Checked = true;
            dailyChartToolStripButton.Checked = false;
            chartPanel.ChartMode = 1;
        }

        private void dailyChartToolStripButton_Click(object sender, EventArgs e)
        {
            dailyChartToolStripMenuItem.PerformClick();
        }

        private void weeklyChartToolStripButton_Click(object sender, EventArgs e)
        {
            weeklyChartToolStripMenuItem.PerformClick();
        }

        private void comboBoxBrandList_SelectedIndexChanged(object sender, EventArgs e)
        {
            listBoxBrandList.SuspendLayout();
            listBoxBrandList.Items.Clear();
            var bl = (BrandList)((ComboBox)sender).SelectedItem;
            foreach (var code in bl.List)
                listBoxBrandList.Items.Add(GlobalEnv.BrandData[code]);
            listBoxBrandList.ResumeLayout(false);
        }

        private void listBoxBrandList_SelectedIndexChanged(object sender, EventArgs e)
        {
            var brand = (Brand)((ListBox)sender).SelectedItem;
            if (brand == null)
                return;
            chartPanel.SelectedCode = brand.Code;
            SetBrandInfo(brand);
        }

        /// <summary>
        /// 銘柄情報を表示する。
        /// </summary>
        /// <param name="brand">銘柄オブジェクト</param>
        private void SetBrandInfo(Brand brand)
        {
            labelCode.Text = brand.Code + " " + brand.MarketName;
            labelBrandName.Text = brand.Name;
        }

        /// <summary>
        /// 価格情報を表示する。
        /// </summary>
        /// <param name="price">価格オブジェクト</param>
        private void SetPriceInfo(Price price)
        {
            labelDate.Text = price.Date.ToString("yyyy/MM/dd");
            labelOpenValue.Text = price.Open.ToString("#,#");
            labelHighValue.Text = price.High.ToString("#,#");
            labelLowValue.Text = price.Low.ToString("#,#");
            labelCloseValue.Text = price.Close.ToString("#,#");
            labelVolumeValue.Text = price.Volume.ToString("#,#.#");
        }

        private void manualToolStripMenuItem_Click(object sender, System.EventArgs e)
        {
            Process.Start(Global.PathMan);
        }

        private void versionToolStripMenuItem_Click(object sender, System.EventArgs e)
        {
            Form dialog = new VersionDialog();
            dialog.ShowDialog(this);
        }

        private void searchToolStripButton_Click(object sender, EventArgs e)
        {
            if (toolStripTextBox.Text == "")
                return;
            List<Brand> brands;
            Brand b = GlobalEnv.BrandData[toolStripTextBox.Text];
            if (b.Unit > 0)
            {
                brands = new List<Brand>();
                brands.Add(b);
            }
            else
                brands = GlobalEnv.BrandData.Search(toolStripTextBox.Text);
            ContextMenu contextMenu = new ContextMenu();
            foreach (Brand brand in brands)
            {
                var menuItem = new MenuItem();
                menuItem.Text = brand.ToString();
                menuItem.Tag = brand;
                menuItem.Click += new EventHandler(menuItemSearchedBrand_Click);
                contextMenu.MenuItems.Add(menuItem);
            }
            contextMenu.Show(mainToolStrip,
                new Point(searchToolStripButton.Bounds.Left,
                    searchToolStripButton.Bounds.Bottom));
        }

        private void menuItemSearchedBrand_Click(object sender, System.EventArgs e)
        {
            listBoxBrandList.SelectedItem = null;
            var brand = (Brand)((MenuItem)sender).Tag;
            chartPanel.SelectedCode = brand.Code;
            SetBrandInfo(brand);
        }

        private void toolStripTextBox_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == (char)13)
                searchToolStripButton.PerformClick();
        }

        private void priceUpdateToolStripMenuItem_Click(object sender, EventArgs e)
        {
            var lastModified = GlobalEnv.BrandData.LastModified;
            using (var updateDialog = new PriceUpdateDialog())
                updateDialog.ShowDialog();
            chartPanel.UpdatePrices();
            if (lastModified == GlobalEnv.BrandData.LastModified)
                return;
            BrandListInit();
        }

        private void priceUpdateToolStripButton_Click(object sender, EventArgs e)
        {
            priceUpdateToolStripMenuItem.PerformClick();
        }

        InputDateDialog inputDateDialog;

        private void priceDeleteToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (inputDateDialog == null)
                inputDateDialog = new InputDateDialog();
            var dialog = inputDateDialog;
            dialog.Message = "指定した日付以降のデータを削除します。";
            dialog.Value = PriceData.MaxDate;
            dialog.ShowDialog();
            if (dialog.DialogResult != DialogResult.OK)
                return;
            Cursor = Cursors.WaitCursor;
            Application.DoEvents();
            PriceData.Delete(dialog.Value);
            Cursor = Cursors.Default;
            chartPanel.UpdatePrices();
        }

        DataConvertDialog dataConvertDialog;

        private void priceConvertToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (dataConvertDialog == null)
                dataConvertDialog = new DataConvertDialog();
            var dialog = dataConvertDialog;
            dialog.ShowDialog();
            if (dialog.DialogResult != DialogResult.OK)
                return;
            Cursor = Cursors.WaitCursor;
            Application.DoEvents();
            bool result;
            if (dataConvertDialog.ToCSV)
                result = PriceData.ConvertToCSV(dialog.StartCode.ToString(), dialog.EndCode.ToString());
            else
            {
                result = PriceData.ConvertFromCSV(dialog.StartCode.ToString(), dialog.EndCode.ToString());
                chartPanel.UpdatePrices();
            }
            Cursor = Cursors.Default;
            MessageBox.Show(result ? "変換が終了しました。" : "変換を中断しました。", "株価データの変換", MessageBoxButtons.OK);
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void ptSimToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string path = Path.Combine(Global.DirApp, "PtSim.exe");
            Process.Start(path);
        }

        private void ptSimToolStripButton_Click(object sender, EventArgs e)
        {
            ptSimToolStripMenuItem.PerformClick();
        }

        private void OptionToolStripMenuItem_Click(object sender, EventArgs e)
        {
            using (var dialog = new OptionDialog())
            {
                DialogResult result = dialog.ShowDialog(this);
                if (result != DialogResult.OK)
                    return;
                // 設定を描画に反映させる。
                var p = GlobalEnv.ProtraConfig;
                chartPanel.ChartNum = p.ChartNum;
                chartPanel.ChartForeColor = Color.FromArgb(p.ChartForeColor);
                chartPanel.ChartBackColor = Color.FromArgb(p.ChartBackColor);
                chartPanel.DrawLastWeek = p.DrawLastWeek;
                chartPanel.UseDifferentChart = p.UseDifferentChart;
            }
        }

        private void listEditToolStripMenuItem_Click(object sender, EventArgs e)
        {
            using (var dialog = new EditBrandListDialog())
                dialog.ShowDialog(this);
            BrandListInit();
        }

        private void listAddtoolStripMenuItem_Click(object sender, EventArgs e)
        {
            int index = comboBoxBrandList.SelectedIndex;
            string code = chartPanel.SelectedCode;
            if (index == -1 || code == null)
                return;
            if (index < 3)
            {
                MessageBox.Show("この銘柄リストには追加できません。", "エラー", MessageBoxButtons.OK);
                return;
            }
            var bl = (BrandList)comboBoxBrandList.Items[index];
            if (bl.List.Contains(code))
                return;
            listBoxBrandList.Items.Add(GlobalEnv.BrandData[code]);
            bl.List.Add(code);
            GlobalEnv.BrandListConfig.Save();
        }

        private void listDelToolStripMenuItem_Click(object sender, EventArgs e)
        {
            int index = comboBoxBrandList.SelectedIndex;
            string code = chartPanel.SelectedCode;
            if (index == -1 || code == null)
                return;
            if (index < 3)
            {
                MessageBox.Show("この銘柄リストからは削除できません。", "エラー", MessageBoxButtons.OK);
                return;
            }
            var bl = (BrandList)comboBoxBrandList.Items[index];
            if (!bl.List.Contains(code))
                return;
            var li = listBoxBrandList.SelectedIndex;
            listBoxBrandList.Items.Remove(GlobalEnv.BrandData[code]);
            if (li == listBoxBrandList.Items.Count)
                listBoxBrandList.SelectedIndex = li - 1;
            else
                listBoxBrandList.SelectedIndex = li;
            bl.List.Remove(code);
            GlobalEnv.BrandListConfig.Save();
        }
    }
}