// ALL RIGHTS RESERVED:
// ====================
// The contents of this file, and associated files in this directory, are 
// Copyright (C) SPT , all rights reserved, 2009.
// All software Source Code, Images, Database-Design and code, Graphics Design 
// and source files, and related content (collectively referred to as SOURCE) are 
// Copyright (c) SPT, 2009, All Rights Reserved.
// http://SerialPortTool.com

// PTZ Controller is a Registered Trademark of SerialPortTool.com.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Diagnostics;
using System.Windows.Forms;
using PTZController.Logic;
using PTZController.Controls;
using SPT.PTZ.Core;

namespace PTZController
{
    public partial class TourForm : SkinForm
    {
        private const string TourConfigExt = "Tour Configuration Files(*.tour)|*.tour|All Files(*.*)|*.*||";

        private const string PromptTitle = "Confirm";
        private const string DeletePrompt = "Do you want to delete the selected item?";
        private const string ClearPrompt = "Do you want to clear ALL items in the list?";

        private Spt.Share.Data.StaySpan _span;

        public Spt.Share.Data.StaySpan Span
        {
            get { return _span; }
            set { _span = value; }
        }

        private Logic.TourItemCollection _tourItems = new TourItemCollection();

        public Logic.TourItemCollection TourItems
        {
            get { return _tourItems; }
            set { _tourItems = value; }
        }

        private Logic.TourItem _previousItem = new TourItem(0, 0, new Spt.Share.Data.StaySpan(TourItem.DefaultSpanValue, Spt.Share.Data.SpanUnit.Second));

        private Logic.CameraItemList _cameras;

        public Logic.CameraItemList Cameras
        {
            get { return _cameras; }
            set { _cameras = value; }
        }

        private Core.ScanMode _scanWay;

        public Core.ScanMode ScanWay
        {
            get { return _scanWay; }
            set { _scanWay = value; }
        }

        private bool m_clockWise;

        public bool ClockWise
        {
            get { return m_clockWise; }
            set { m_clockWise = value; }
        }

        private int m_scanSpeed;

        public int ScanSpeed
        {
            get { return m_scanSpeed; }
            set { m_scanSpeed = value; }
        }

        public enum TourState
        {
            Running = 0,
            Stopped,
            Paused
        }

        /// <summary>
        /// Tour state
        /// </summary>
        private TourState _state = TourState.Stopped;

        public TourState State
        {
            get { return _state; }
            set { _state = value; }
        }

        private Controller _controller;

        public Controller Controller
        {
            get { return _controller; }
            set { _controller = value; }
        }
	
        public TourForm()
        {
            InitializeComponent();
        }

        private void TourForm_Load(object sender, EventArgs e)
        {
            _speedSlider.ValueChanged += new EventHandler(_speedSlider_ValueChanged);

            _presetScanRadio.Checked = ScanWay == PTZController.Core.ScanMode.presetScan;
            _autoPanRadio.Checked = !_presetScanRadio.Checked;

            _defaultSpanEdit.Span = this.Span;
            _defaultSpanEdit.ApplyValue();

            _clockWiseButton.PressedFlag = ClockWise;
            _counterClockWiseButton.PressedFlag = !ClockWise;

            _speedSlider.Value = ScanSpeed;

            ShowTourItems();
            UpdateButtonsState();

            helpProvider1.HelpNamespace = @"PTZ Helper.chm";

            ApplyStyle();

        }

        private void _speedSlider_ValueChanged(object sender, EventArgs e)
        {
            _speedLabel.Text = _speedSlider.Value.ToString();
        }

        private void _addButton_Click(object sender, EventArgs e)
        {
            DoAdd();
        }

        private void DoAdd()
        {
            PresetItemForm f = new PresetItemForm();

            f.Item = _previousItem;
            f.Cameras = this.Cameras;
            f.Controller = Controller;

            if (f.ShowDialog() == DialogResult.OK)
            {
                _previousItem = f.Item.Clone() as Logic.TourItem;
                TourItems.Items.Add(f.Item);
                AddItemToShow(f.Item);
                _presetsListView.Focus();

                UpdateButtonsState();
            }
        }

        private void AddItemToShow(TourItem item)
        {
            string[] texts = 
            { 
                Cameras[item.Camera].Name,
                Cameras[item.Camera].Presets[item.Preset].Name,
                item.Span.ToString()
            };

            ListViewItem lvi = new ListViewItem(texts);

            lvi.ImageIndex = 0;
            lvi.Tag = item;
            _presetsListView.Items.Add(lvi);
        }


        private void EditItemToShow(int index, TourItem item)
        {
            string[] texts = 
            { 
                Cameras[item.Camera].Name,
                Cameras[item.Camera].Presets[item.Preset].Name,
                item.Span.ToString()
            };

            ListViewItem lvi = new ListViewItem(texts);

            lvi.ImageIndex = 0;
            lvi.Tag = item;
            _presetsListView.Items[index] = lvi;
        }
        
        private void _editButton_Click(object sender, EventArgs e)
        {
            DoEdit();
        }

        private void DoEdit()
        {
            if (_presetsListView.SelectedIndices.Count > 0)
            {
                int sel = _presetsListView.SelectedIndices[0];

                PresetItemForm f = new PresetItemForm();

                f.Controller = Controller;
                f.Item = TourItems.Items[sel].Clone() as Logic.TourItem;
                f.Cameras = this.Cameras;

                if (f.ShowDialog() == DialogResult.OK)
                {
                    _previousItem = f.Item.Clone() as Logic.TourItem;
                    TourItems.Items[sel] = f.Item;
                    EditItemToShow(sel, f.Item);
                    _presetsListView.Focus();
                }
            }
        }

        private void _exitButton_Click(object sender, EventArgs e)
        {
            this.Span = _defaultSpanEdit.Span;
            Close();
        }

        private void UpdateButtonsState()
        {
            bool flag = false;
            bool idle = (State == TourState.Stopped);
            int cnt = _presetsListView.Items.Count;
            int sel = -1;

            if (_presetsListView.SelectedIndices.Count > 0)
            {
                sel = _presetsListView.SelectedIndices[0];
                flag = true;
            }

            _addButton.Enabled = idle;
            _editButton.Enabled = flag && idle;
            _deleteButton.Enabled = flag && idle;
            _clearButton.Enabled = idle;

            _upButton.Enabled = flag && idle && ((cnt > 1) && (sel > 0));
            _downButton.Enabled = flag && idle && ((cnt > 1 && sel < cnt - 1));
            _topButton.Enabled = flag && idle && ((cnt > 1) && (sel > 0));
            _bottomButton.Enabled = flag && idle && ((cnt > 1 && sel < cnt - 1));

            _runButton.Enabled = (State == TourState.Stopped) || (State == TourState.Paused);
            _pauseButton.Enabled = (State == TourState.Running);
            _stopButton.Enabled = (State != TourState.Stopped);

            _saveButton.Enabled = idle;
            _loadButton.Enabled = idle;

            _exitButton.Enabled = idle;

            _presetsListView.Enabled = idle;
            _defaultSpanEdit.Enabled = idle;

            _gotoButton.Enabled = idle && (sel >= 0);

            _clearButton.Enabled = idle && (cnt > 0);

            _clockWiseButton.Enabled = idle;
            _counterClockWiseButton.Enabled = idle;

            _speedSlider.Enabled = idle;

            _presetScanRadio.Enabled = (State == TourState.Stopped);
            _autoPanRadio.Enabled = (State == TourState.Stopped);
            picAutoPan.Visible = (!_autoPanRadio.Enabled) && _autoPanRadio.Checked;
            picPresetScan.Visible = (!_presetScanRadio.Enabled) && _presetScanRadio.Checked;
        }

        private void _presetsListView_DoubleClick(object sender, EventArgs e)
        {
            DoEdit();
        }

        private void _saveButton_Click(object sender, EventArgs e)
        {
            SaveFileDialog dlg = new SaveFileDialog();

            dlg.Filter = TourConfigExt;

            if (dlg.ShowDialog() == DialogResult.OK)
	        {
		         string fName = dlg.FileName;
                 TourItems.Save(fName);
	        }
        }

        private void _loadButton_Click(object sender, EventArgs e)
        {
            OpenFileDialog dlg = new OpenFileDialog();

            dlg.Filter = TourConfigExt;

            if (dlg.ShowDialog() == DialogResult.OK)
            {
                string fName = dlg.FileName;
                TourItems = TourItemCollection.Load(fName);

                ShowTourItems();
            }
        }

        private void ShowTourItems()
        {
            _presetsListView.Items.Clear();

            for (int i = 0; i < TourItems.Items.Count; i++)
            {
                AddItemToShow(TourItems.Items[i]);
            }

            for (int i = 0; i < TourItems.Items.Count; i++)
            {
                Debug.WriteLine(string.Format("LV {0} <-> Data {1}", _presetsListView.Items[i].SubItems[0].Text, TourItems.Items[i].Camera + 1));
            }
        }

        private void _deleteButton_Click(object sender, EventArgs e)
        {
            if (_presetsListView.SelectedIndices.Count > 0)
            {
                DialogResult n = MessageBox.Show(DeletePrompt, PromptTitle, MessageBoxButtons.YesNo);

                if (n == DialogResult.Yes)
                {
                    int sel = _presetsListView.SelectedIndices[0];

                    _presetsListView.Items.RemoveAt(sel);
                    TourItems.Items.RemoveAt(sel);

                    UpdateButtonsState();
                }
            }
        }

        private void _clearButton_Click(object sender, EventArgs e)
        {
            DialogResult n = MessageBox.Show(ClearPrompt, PromptTitle, MessageBoxButtons.YesNo);

            if (n == DialogResult.Yes)
            {
                _presetsListView.Items.Clear();
                TourItems.Items.Clear();

                UpdateButtonsState();
            }
        }

        private void _presetsListView_SelectedIndexChanged(object sender, EventArgs e)
        {
            UpdateButtonsState();
        }

        private void _upButton_Click(object sender, EventArgs e)
        {
            int sel = GetSelectedItem();
            SwapItem(sel, sel - 1);
        }

        private void _downButton_Click(object sender, EventArgs e)
        {
            int sel = GetSelectedItem();
            SwapItem(sel, sel + 1);
        }

        private void _topButton_Click(object sender, EventArgs e)
        {
            int sel = GetSelectedItem();
            SwapItem(sel, 0);
        }

        private void _bottomButton_Click(object sender, EventArgs e)
        {
            int sel = GetSelectedItem();
            SwapItem(sel, _presetsListView.Items.Count - 1);
        }

        private int GetSelectedItem()
        {
            int sel = -1;

            if (_presetsListView.SelectedIndices.Count > 0)
            {
                sel = _presetsListView.SelectedIndices[0];
            }

            return sel;
        }

        private void SwapItem(int source, int target)
        {
            ListViewItem tmp = _presetsListView.Items[source];

            _presetsListView.Items.RemoveAt(source);
            _presetsListView.Items.Insert(target, tmp);

            TourItem it = TourItems.Items[source];

            TourItems.Items.RemoveAt(source);
            TourItems.Items.Insert(target, it);

            _presetsListView.Items[target].Selected = true;
            _presetsListView.Focus();

            for (int i = 0; i < TourItems.Items.Count; i++)
            {
                Debug.WriteLine(string.Format("LV {0} <-> Data {1}", _presetsListView.Items[i].SubItems[0].Text, TourItems.Items[i].Camera + 1));
            }
        }

        private void _runButton_Click(object sender, EventArgs e)
        {
            UpdateScanWay();

            DoStart();
        }

        private void UpdateScanWay()
        {
            if (_presetScanRadio.Checked)
            {
                ScanWay = PTZController.Core.ScanMode.presetScan;
            }
            else
            {
                ScanWay = PTZController.Core.ScanMode.autoPan;
            }
        }

        private void DoStart()
        {
            ClockWise = _clockWiseButton.PressedFlag;
            ScanSpeed = _speedSlider.Value;

            if (ScanWay == PTZController.Core.ScanMode.presetScan)
            {
                bool reset = (State == TourState.Stopped);

                TourItems.Start(reset);

                if (reset)
                {
                    TourItems.Tour(Controller, _defaultSpanEdit.Span);
                }

                _tourTimer.Enabled = true;

                _clockWiseButton.Disable = Properties.Resources.btn_clockwise_dis;
                _counterClockWiseButton.Disable = Properties.Resources.btn_counterclockwise_dis;

                UpdateArrow();
            }
            else
            {
                _clockWiseButton.Disable = ClockWise ? Properties.Resources.btn_clockwise_select_disable : Properties.Resources.btn_clockwise_dis;
                _counterClockWiseButton.Disable = ClockWise ? Properties.Resources.btn_counterclockwise_dis : Properties.Resources.btn_counterclockwise_select_disable;

                _controller.AutoScan(true, ClockWise, ScanSpeed);
            }

            State = TourState.Running;

            UpdateButtonsState();
        }

        private void _pauseButton_Click(object sender, EventArgs e)
        {
            DoPause();
        }

        private void DoPause()
        {
            State = TourState.Paused;

            if (ScanWay == PTZController.Core.ScanMode.presetScan)
            {
                _tourTimer.Enabled = false;
            }
            else
            {
                _controller.AutoScan(false, ClockWise, ScanSpeed);
            }

            UpdateButtonsState();
        }

        private void _stopButton_Click(object sender, EventArgs e)
        {
            DoStop();
        }

        private void DoStop()
        {
            State = TourState.Stopped;

            if (ScanWay == PTZController.Core.ScanMode.presetScan)
            {
                _tourTimer.Enabled = false;

                for (int i = 0; i < _presetsListView.Items.Count; i++)
                {
                    _presetsListView.Items[i].ImageIndex = 0;
                }

                TourItems.Stop();
            }
            else
            {
                _controller.AutoScan(false, ClockWise, ScanSpeed);
            }

            UpdateButtonsState();
        }

        private void _tourTimer_Tick(object sender, EventArgs e)
        {
            if (_state == TourState.Running)
            {
                UpdateArrow();
                TourItems.Tour(Controller, _defaultSpanEdit.Span);
            }
        }

        private void UpdateArrow()
        {
            int cur = TourItems.Cursor;

            if (_presetsListView.Items.Count > 0)
            {
                if (cur > 0)
                {
                    _presetsListView.Items[cur - 1].ImageIndex = 0;
                }
                else
                {
                    _presetsListView.Items[_presetsListView.Items.Count - 1].ImageIndex = 0;
                }

                _presetsListView.Items[cur].ImageIndex = 1;
            }
        }

        private void TourForm_FormClosed(object sender, FormClosedEventArgs e)
        {
            if (State != TourState.Stopped)
            {
                DoStop();                
            }

            ClockWise = _clockWiseButton.PressedFlag;
            ScanSpeed = _speedSlider.Value;

            UpdateScanWay();
        }

        private void _goToPresetButton_Click(object sender, EventArgs e)
        {
            if (_presetsListView.SelectedIndices.Count > 0)
            {
                int sel = _presetsListView.SelectedIndices[0];
                int old = Controller.Address;

                Controller.Address = (byte)(TourItems.Items[sel].Camera);
                Controller.SendCommand(SPT.PTZ.Core.PtzFunction.SelectCamera, TourItems.Items[sel].Camera);
                Controller.SendCommand(SPT.PTZ.Core.PtzFunction.GotoPreset, TourItems.Items[sel].Preset + 1);

                Controller.Address = (byte)old;
                Controller.SendCommand(SPT.PTZ.Core.PtzFunction.SelectCamera, old);

                _presetsListView.Focus();
            }
        }

        private void _clockWiseButton_Click(object sender, EventArgs e)
        {
            if (!_clockWiseButton.PressedFlag)
            {
                _counterClockWiseButton.PressedFlag = false;
            }
        }

        private void _counterClockWiseButton_Click(object sender, EventArgs e)
        {
            if (!_counterClockWiseButton.PressedFlag)
            {
                _clockWiseButton.PressedFlag = false;
            }
        }

        private void helpButton_Click(object sender, EventArgs e)
        {
            Help.ShowHelp(this, ProductInfo.HelpFile, HelpNavigator.Topic, "Reference\\AutoScanDialog.htm");
        }

        private void _defaultSpanEdit_Load(object sender, EventArgs e)
        {

        }
    }
}