using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Threading;
using System.Threading;
using EvoBoat.EvoAlg;
using EvoBoat.EvoAlg.IntDivision;

namespace MachUtilPlanner
{
    using VS = VecSolution<IntVector, int>;
    using EA = EAlg<MachUtilProblem, VecSolution<IntVector, int>, IntVector, int>;
    using ATD = AlgTestData<MachUtilProblem, VecSolution<IntVector, int>, IntVector, int>;
    using Excel = Microsoft.Office.Interop.Excel;

    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        MachUtilProblem problem;
        IntDivisionSolutionFactory<MachUtilProblem, VS> factory;
        EA[] algs;
        EA[] cAlgs;
        List<ATD> testData;

        public MainWindow()
        {
            InitializeComponent();
            this.Loaded += Window_Loaded;
            rbMaxIters.Checked += rbMaxIters_Checked;
            rbMaxIters.Unchecked += rbMaxIters_Unchecked;
            chkPorg.Checked += chkPorg_Checked;
            chkPorg.Unchecked += chkPorg_Unchecked;
            btnRun.Click += btnRun_Click;
            btnClear.Click += btnClear_Click;
        }        

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            /*MachUtilProblem op = MachUtilProblem.TestProblem(ThreePhaseFailureRate.EnginFailureRate1, 14600, 35, 8, 1.5, 0.2, 0.7, 0.1);
            EA alg = new IntDiv_EBOAlg<MachUtilProblem, VS>(op);
            alg.SetParameters();
            alg.SolveF(2000);
            MessageBox.Show(alg.Best.ToString() + string.Format("({0})", alg.Best.Content.Sum()));
            int K;
            op.Evaluate(alg.Best.Content, out K);
            //System.Windows.MessageBox.Show(K.ToString());

            tbResult.AppendText(new IntVector(op.UseTime).ToString());
            tbResult.AppendText("\r\n");
            tbResult.AppendText(new IntVector(op.T0).ToString());
            tbResult.AppendText("\r\n");*/

            foreach (MachUtilProblem p in TestProblems.Problems)
                cmbProblems.Items.Add(p);
            //cmbProblems.Items.Add(op);
            cmbProblems.SelectionChanged += CmbProblems_SelectionChanged;
            cmbProblems.SelectedIndex = 0;
            algs = new EA[] {
                new IntDiv_GA<MachUtilProblem, VS>(), new IntDiv_PSOAlg<MachUtilProblem, VS>(), new IntDiv_CLPSOAlg<MachUtilProblem, VS>(), new IntDiv_DEAlg<MachUtilProblem, VS>(), new IntDiv_BBOAlg<MachUtilProblem, VS>(), new IntDiv_BlendBBOAlg<MachUtilProblem, VS>(), new IntDiv_EBOAlg<MachUtilProblem, VS>(), new MUP_WWOAlg()
            };
            for (int i = 0; i < algs.Length; i++)
            {
                lbAlgs.Items.Add(algs[i]);
            }
            //lbAlgs.SelectedItem = lbAlgs.Items[lbAlgs.Items.Count - 1];
            lbAlgs.SelectAll();
            lbAlgs.Focus();
        }

        private void CmbProblems_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            problem = (MachUtilProblem)cmbProblems.SelectedItem;
        }

        private void btnAlgSel_Click(object sender, RoutedEventArgs e)
        {

        }
        private void rbMaxIters_Checked(object sender, RoutedEventArgs e)
        {
            tbMaxIters.IsEnabled = true;
            tbMaxNfes.IsEnabled = false;
        }

        void rbMaxIters_Unchecked(object sender, RoutedEventArgs e)
        {
            tbMaxIters.IsEnabled = false;
            tbMaxNfes.IsEnabled = true;
        }

        private void chkPorg_Checked(object sender, RoutedEventArgs e)
        {
            tbIntvs.IsEnabled = true;
        }

        void chkPorg_Unchecked(object sender, RoutedEventArgs e)
        {
            tbIntvs.IsEnabled = false;
        }

        void btnRun_Click(object sender, RoutedEventArgs e)
        {
            if (lbAlgs.SelectedIndex == -1)
            {
                MessageBox.Show("请选择至少一个算法");
                return;
            }
            int runs = int.Parse(tbRuns.Text);
            int upper = (rbMaxIters.IsChecked == true) ? int.Parse(tbMaxIters.Text) : int.Parse(tbMaxNfes.Text);
            int interval = (chkPorg.IsChecked == true) ? int.Parse(tbIntvs.Text) : 0;
            if (interval > 0 && upper / interval > 670)
            {
                if (MessageBox.Show("详细数据列数超过670,是否继续?", "提示", MessageBoxButton.OKCancel) == MessageBoxResult.Cancel)
                    return;
            }
            factory = new IntDivisionSolutionFactory<MachUtilProblem, VecSolution<IntVector, int>>(problem);
            cAlgs = new EA[lbAlgs.SelectedItems.Count];
            testData = new List<ATD>(cAlgs.Length);
            for (int i = 0; i < cAlgs.Length; i++)
                cAlgs[i] = (EA)lbAlgs.SelectedItems[i];
            for (int i = 0; i < cAlgs.Length; i++)
            {
                EA alg = cAlgs[i];
                new Thread(() =>
                {
                    DispatcherOperation ar = this.Dispatcher.BeginInvoke(new Action(() =>
                    {
                        testData.Add(ATD.Get(alg, problem, factory, runs, upper, interval, rbMaxNfes.IsChecked == true));
                    }));
                    ar.Completed += ar_Completed;
                }).Start();
            }
        }

        void ar_Completed(object sender, EventArgs e)
        {
            tbResult.AppendText(testData[testData.Count - 1].ToString());
        }

        void btnClear_Click(object sender, RoutedEventArgs e)
        {
            tbResult.Clear();
            testData = null;
        }

        private void btnExport_Click(object sender, RoutedEventArgs e)
        {
            if (tbResult.Text == "" || testData == null)
            {
                MessageBox.Show("无数据可导出");
                return;
            }
            if (testData[0].Data.GetLength(1) > 670)
            {
                MessageBox.Show("数据列数不能超过670");
                return;
            }
            try
            {
                Excel.Application app = new Excel.Application();
                app.Visible = true;
                Excel.Workbook book1 = app.Workbooks.Add();
                Excel.Worksheet[] sheets = new Excel.Worksheet[cAlgs.Length];
                sheets[0] = book1.Worksheets.get_Item(1);
                sheets[0].Name = cAlgs[0].Name;
                testData[0].WriteExcel(sheets[0]);
                for (int i = 1; i < testData.Count; i++)
                {
                    sheets[i] = book1.Worksheets.Add();
                    sheets[i].Name = cAlgs[i].Name;
                    testData[i].WriteExcel(sheets[i]);
                }
            }
            catch (Exception exc)
            {
                MessageBox.Show(exc.Message);
            }
        }
    }
}
