using System;
using System.ComponentModel;
using System.IO;
using System.Windows.Forms;
using Zanetti.Data;

namespace Zanetti
{
    public partial class DecupleData : Form
    {
        public DecupleData()
        {
            InitializeComponent();
        }

        public static void Decuple()
        {
            if (IsDecoupled())
                return;
            using (var dialog = new DecupleData())
            {
                if (dialog.ShowDialog() == DialogResult.Cancel)
                    Application.Exit();
            }
        }

        private static bool IsDecoupled()
        {
            var farm = Env.BrandCollection.FindBrand(9984).CreateFarm(ChartFormat.Daily); // ソフトバンクでテスト
            if (farm.IsEmpty || farm.FirstDate >= 20140721) // そもそも過去のデータがない
                return true;
            var dates = new[] {20140718, 20140618, 20140519};
            var closes = new[] {7654, 7610, 6766};
            for (var i = 0; i < dates.Length; i++)
            {
                if (farm.LastDate < dates[i])
                    continue;
                var head = farm.DateToIndex(dates[i]) * DataFarm.RECORD_LENGTH;
                return farm.GetInt(head + DataFarm.CLOSE_OFFSET) == closes[i] * 10;
            }
            return false;
        }

        private void buttonOk_Click(object sender, EventArgs e)
        {
            buttonOk.Enabled = false;
            buttonIgnore.Enabled = false;
            Cursor = Cursors.WaitCursor;
            backgroundWorkerDecuple.RunWorkerAsync();
        }

        private void backgroundWorkerDecuple_DoWork(object sender, DoWorkEventArgs e)
        {
            var worker = (BackgroundWorker)sender;
            Backup(worker);
            Convert(worker);
        }

        private void Backup(BackgroundWorker worker)
        {
            var org = Path.Combine(Env.GetAppDir(), @"data");
            var back = Path.Combine(Env.GetAppDir(), @"data\back");
            if (Directory.Exists(back))
                throw new Exception(back + "\nバックアップディレクトリが存在します。\n移動するか削除してからやり直してください。");
            Directory.CreateDirectory(back);
            worker.ReportProgress(0, "バックアップ中");
            var files = Directory.CreateDirectory(org).GetFiles();
            var i = 0;
            foreach (var finfo in files)
            {
                finfo.CopyTo(Path.Combine(back, finfo.Name)).LastWriteTime = finfo.LastWriteTime;
                worker.ReportProgress(100 * i++ / files.Length, "バックアップ中");
            }
        }

        private void Convert(BackgroundWorker worker)
        {
            var i = 0;
            worker.ReportProgress(0, "変換中");
            foreach (AbstractBrand br in Env.BrandCollection.Values)
            {
                var basic = br as BasicBrand;
                if (basic == null || basic.Market == MarketType.B || basic.Market == MarketType.Custom)
                    continue;
                using (var farm = (DailyDataFarm)br.CreateDailyFarm(0))
                {
                    if (!farm.IsEmpty)
                    {
                        DoupleFarm(farm);
                        farm.Save(Util.GetDailyDataFileName(br.Code));
                    }
                }
                worker.ReportProgress(100 * i++ / Env.BrandCollection.StockBrandCount, "変換中");
            }
        }

        private void DoupleFarm(DataFarm farm)
        {
            for (var i = 0; i < farm.FilledLength; i++)
            {
                var head = i * DataFarm.RECORD_LENGTH;
                var open = farm.GetInt(head + DataFarm.OPEN_OFFSET);
                var high = farm.GetInt(head + DataFarm.HIGH_OFFSET);
                var low = farm.GetInt(head + DataFarm.LOW_OFFSET);
                var close = farm.GetInt(head + DataFarm.CLOSE_OFFSET);

                var raw = farm.RawDataImage;
                DataFarm.SetInt(raw, head + DataFarm.OPEN_OFFSET, open * 10);
                DataFarm.SetInt(raw, head + DataFarm.HIGH_OFFSET, high * 10);
                DataFarm.SetInt(raw, head + DataFarm.LOW_OFFSET, low * 10);
                DataFarm.SetInt(raw, head + DataFarm.CLOSE_OFFSET, close * 10);
            }
        }

        private void backgroundWorkerDecuple_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            labelProgress.Text = (string)e.UserState;
            progressBar1.Value = e.ProgressPercentage;
        }

        private void backgroundWorkerDecuple_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Error != null)
            {
                MessageBox.Show(e.Error.Message, "変換エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
                Application.Exit();
            }
            DialogResult = DialogResult.OK;
            Close();
        }
    }
}