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.Threading;
using System.Threading;
using System.Reflection;
using EvoBoat.EvoAlg;

namespace NumTest
{
    using NOP = NumOptProblem<VecSolution<EvoBoat.EvoAlg.Vector, double>>;
    using VecSol = VecSolution<EvoBoat.EvoAlg.Vector, double>;
    using EA = EAlg<NumOptProblem<VecSolution<EvoBoat.EvoAlg.Vector, double>>, VecSolution<EvoBoat.EvoAlg.Vector, double>, EvoBoat.EvoAlg.Vector, double>;
    using ATD = AlgTestData<NumOptProblem<VecSolution<EvoBoat.EvoAlg.Vector, double>>, VecSolution<EvoBoat.EvoAlg.Vector, double>, EvoBoat.EvoAlg.Vector, double>;
    using Excel = Microsoft.Office.Interop.Excel;

    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        NOP problem;
        VectorSolutionFactory<NOP, VecSolution<EvoBoat.EvoAlg.Vector, double>> factory;
        EA[] algs;
        EA[] cAlgs;
        List<ATD> testData;

        public MainWindow()
        {
            InitializeComponent();
            this.Loaded += Window_Loaded;
            rbYao23.Checked += rbYao23_Checked;
            rbCEC14.Checked += rbCEC14_Checked;
            rbCEC15.Checked += rbCEC15_Checked;
            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)
        {
            cmbProblems.SelectionChanged += cmbProblems_SelectionChanged;
            cmbProblems.SelectedIndex = 0;
            algs = new EA[] {
                new EvoBoat.EvoAlg.GA.Num_GA<VecSol>(), new EvoBoat.EvoAlg.GA.Num_SGA<VecSol>(), new EvoBoat.EvoAlg.PSO.Num_PSOAlg<VecSol>(), new EvoBoat.EvoAlg.PSO.Num_CLPSOAlg<VecSol>(), new EvoBoat.EvoAlg.DE.Num_DEAlg<VecSol>(), new EvoBoat.EvoAlg.BBO.Num_BBOAlg<VecSol>(), new EvoBoat.EvoAlg.BBO.Num_BlendBBOAlg<VecSol>(), new EvoBoat.EvoAlg.BBO.Num_EBOAlg<VecSol>(), new EvoBoat.EvoAlg.WWO.Num_WWOAlg<VecSol>(), new EvoBoat.EvoAlg.WWO.Num_VarWWOAlg<VecSol>(), new EvoBoat.EvoAlg.WWO.Num_SimWWOAlg<VecSol>(), new EvoBoat.EvoAlg.WWO.Num_DWWOAlg<VecSol>()
            };
            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();
            rbYao23.IsChecked = true;
        }

        private void rbYao23_Checked(object sender, RoutedEventArgs e)
        {
            cmbProblems.Items.Clear();
            foreach (NumOptProblem<VecSol> p in YaoTestProblems.Problems)
                cmbProblems.Items.Add(p);
            cmbProblems.SelectedIndex = 0;
        }

        private void rbCEC14_Checked(object sender, RoutedEventArgs e)
        {
            cmbProblems.Items.Clear();
            foreach (NumOptProblem<VecSol> p in CEC14TestProblems.Problems30D)
                cmbProblems.Items.Add(p);
            cmbProblems.SelectedIndex = 0;
        }

        private void rbCEC15_Checked(object sender, RoutedEventArgs e)
        {
            cmbProblems.Items.Clear();
            foreach (NumOptProblem<VecSol> p in CEC15TestProblems.Problems30D)
                cmbProblems.Items.Add(p);
            cmbProblems.SelectedIndex = 0;
        }

        void cmbProblems_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            problem = (NumOptProblem<VecSol>)cmbProblems.SelectedItem;
        }

        private void btnAlgSel_Click(object sender, RoutedEventArgs e)
        {
            /*AlgSelectionWindow win = new AlgSelectionWindow(algs);
            if (win.ShowDialog() == true)
            {
                algs = win.Algorithms.ToArray();
                lbAlgs.Items.Clear();
                for (int i = 0; i < algs.Length; i++)
                    lbAlgs.Items.Add(algs[i]);
                lbAlgs.SelectAll();
                lbAlgs.Focus();
            }*/
        }

        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 VectorSolutionFactory<NumOptProblem<VecSol>, VecSol> (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);
            }
        }
    }
}
