using System;
using System.ComponentModel;
using System.Threading;
using System.Windows.Forms;

namespace PinyinModel
{
    public partial class FormMain : Form
    {
		PinyinModel pinyin_model;
        PinyinModel.Solution[] sentences;
        Thread bgWorker_thread;
        string pinyin_string;
		
        internal FormMain(PinyinModel pinyin_model)
        {
			this.Font = View.GetFont();
            this.pinyin_model = pinyin_model;
            InitializeComponent();
			this.statusStrip.Font = this.Font;
            FormMain_Resize(null, null);
        }

        protected override void OnClosing(CancelEventArgs e)
        {
            buttonAbout_Click(this, e);
            base.OnClosing(e);
        }

        private void buttonProcess_Click(object sender, EventArgs e)
        {
            if (bgWorker_thread != null)
            {
                bgWorker_thread.Abort();
                bgWorker_RunWorkerCompleted(sender, null);

                this.bgWorker = new System.ComponentModel.BackgroundWorker();
                this.bgWorker.WorkerReportsProgress = true;
                this.bgWorker.DoWork += new System.ComponentModel.DoWorkEventHandler(this.bgWorker_DoWork);
                this.bgWorker.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(this.bgWorker_RunWorkerCompleted);
                this.bgWorker.ProgressChanged += new System.ComponentModel.ProgressChangedEventHandler(this.bgWorker_ProgressChanged);
            
            }
            else
            {
                bgWorker.RunWorkerAsync();
            }
        }

        private void buttonAbout_Click(object sender, EventArgs e)
        {
            FormAbout frmAbout = new FormAbout();
            frmAbout.ShowDialog();
        }

        private void FormMain_Resize(object sender, EventArgs e)
        {
            textBoxPinyin.Width = this.Width - buttonProcess.Width - buttonOutput.Width - 50;
            buttonOutput.Left = textBoxPinyin.Left + textBoxPinyin.Width + 10;
            buttonProcess.Left = buttonOutput.Left + buttonOutput.Width + 10;
            buttonAbout.Left = buttonProcess.Left;
            listResult.Width = this.Width - 30;
            listResult.Height = this.Height - listResult.Top - statusStrip.Height - 40;
        }

        private void bgWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            bgWorker_thread = Thread.CurrentThread;
            sentences = null;

            pinyin_string = textBoxPinyin.Text;
            try
            {
                pinyin_model.reset();

                bgWorker.ReportProgress(0);
                pinyin_model.parsePinyinString(pinyin_string);

                bgWorker.ReportProgress(1);
                pinyin_model.makeLexiconGraph();

                bgWorker.ReportProgress(2);
                pinyin_model.makeSLMGraph((int)numSolution.Value);

                bgWorker.ReportProgress(3);
                sentences = pinyin_model.makeSentences();
            }
            catch (Exception excp)
            {
                switch (excp.Message)
                {
                    case "InvalidSyllable":
                        bgWorker.ReportProgress(4);
                        break;
                    default:
                        throw excp;
                }
            }
        }

        private void bgWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            switch (e.ProgressPercentage)
            {
                case 0:
                    listResult.Items.Clear();
                    buttonProcess.Text = "取消(&C)";
                    toggleWidgets(true);
                    toolStatus.Text = "正在建立音節圖...";
                    break;
                case 1:
                    toolStatus.Text = "正在建立詞彙圖...";
                    break;
                case 2:
                    toolStatus.Text = "正在建立語言模型圖...";
                    break;
                case 3:
                    toolStatus.Text = "正在計算最優解...";
                    break;
                case 4:
                    toolStatus.Text = "無效拼音: " + pinyin_string;
                    Console.WriteLine("Invalid pinyin string: \"{0}\"", pinyin_string);
                    break;
                default:
                    throw new Exception("InvalidProgress");
            }

        }

        private void bgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e == null || e.Cancelled)
            {
                toolStatus.Text = "已取消";
                Console.WriteLine("Canceled.");
            }
            else
            {
                if (sentences != null)
                {
                    foreach (PinyinModel.Solution item in sentences)
                    {
                        ListViewItem listItem = new ListViewItem(item.sentence);
                        listItem.SubItems.Add("exp(" + item.probability.ToString() + ")");
						listItem.SubItems.Add(item.getPinyinString());
                        listResult.Items.Add(listItem);
                    }
                    listResult.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent);
                    toolStatus.Text = "完成";
                    Console.WriteLine("Finished.");
                }
            }
            toggleWidgets(false);
            textBoxPinyin.Focus();
            buttonProcess.Text = "解析(&P)";
            bgWorker_thread = null;
        }

        private void toggleWidgets(bool working)
        {
            textBoxPinyin.Enabled = !working;
            numSolution.Enabled = !working;
            listResult.Enabled = !working;
        }

        private void buttonOutput_Click(object sender, EventArgs e)
        {
            pinyin_model.output();
        }
    }
}
