using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Windows.Forms;

/*
    Copyright (c) 2010 flixmonk. (http://DVDSwarm.codeplex.com)
    All Rights Reserved.
        
    Redistribution and use in source and binary forms, with or without modification,
    are permitted provided that the following conditions are met:
        
    * Redistributions of source code must retain the above copyright notice, this list
      of conditions and the following disclaimer.
        
    * Redistributions in binary form must reproduce the above copyright notice, this
    list of conditions and the following disclaimer in the documentation and/or other
    materials provided with the distribution. 
        
    * Neither the name of The Flixmonk nor the names of its contributors may be used to
    endorse or promote products derived from this software without specific prior written
    permission.
        
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
    OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
    SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
    OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
    TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
namespace DVDSwarm
{
    /// <summary>
    /// Job Dialog.
    /// </summary>
    public partial class JobDialog : Form
    {
        #region Fields

        private ConfigurationInfo _config = new ConfigurationInfo();
        private Int32 _currentJobIndex = -1;
        private Boolean _isLoading = false;
        private JobInfo _job = new JobInfo();
        private List<JobInfo> _jobs = null;

        #endregion

        #region Methods

        /// <summary>
        /// Creates a new instance of the JobDialog. Used to add a new job.
        /// </summary>
        /// <param name="config">The configuration info.</param>
        /// <exception cref="System.ArgumentNullException">Thrown when config is null.</exception>
        /// <exception cref="System.ArgumentNullException">Thrown when jobs is null.</exception>
        public JobDialog(ConfigurationInfo config, List<JobInfo> jobs)
        {
            if (config == null)
            {
                throw new ArgumentNullException("config");
            }
            if (jobs == null)
            {
                throw new ArgumentNullException("jobs");
            }

            InitializeComponent();

            // Update app icon.
            this.Icon = Properties.Resources.App;

            Text = "Add Job";
            _jobs = jobs;

            // Button Image property does not support transparent images. Load the images
            // from Resources into an ImageList - which does support transparency. 
            imageList1.Images.Add(Properties.Resources.Folder);
            imageList1.Images.Add(Properties.Resources.FolderDown);
            imageList1.TransparentColor = System.Drawing.Color.Fuchsia;
            buttonBrowseVideoSource.Image = imageList1.Images[0];

            _config.Copy(config);
            buttonBrowseVideoSource.Visible = true;
            comboBoxCropAspectRatio.Items.AddRange(FicSprout.Bacicworx.Media.Utility.VideoAspectRatioNames);
            comboBoxCropAspectRatio.Text = FicSprout.Bacicworx.Media.Utility.ConvertVideoAspectRatioToName(
                        FicSprout.Bacicworx.Media.VideoAspectRatio.Aspect_1_78);
            comboBoxCropMode.Items.AddRange(Utility.CropModeNames);
            comboBoxCropMode.Text = Utility.ConvertCropModeToName(_config.Crop);
            comboBoxProcessingOverride.Items.AddRange(FicSprout.Bacicworx.Media.Utility.VideoProcessingTypeNames);
            comboBoxProcessingOverride.Text = FicSprout.Bacicworx.Media.Utility.VideoProcessingTypeNames[0];
            SetTrimLabel(_job.TrimStartTimecode, _job.TrimEndTimecode);

            UpdateUI();
            textBoxVideoInput.Focus();
        }

        /// <summary>
        /// Creates a new instance of the JobDialog populating the form with
        /// the supplied values. Used to edit a job.
        /// </summary>
        /// <param name="config">The configuration info.</param>
        /// <param name="index">The index of the job in the jobs list.</param>
        /// <exception cref="System.ArgumentNullException">Thrown when config is null.</exception>
        /// <exception cref="System.ArgumentNullException">Thrown when jobs is null.</exception>
        public JobDialog(ConfigurationInfo config, List<JobInfo> jobs, Int32 index)
        {
            if (config == null)
            {
                throw new ArgumentNullException("config");
            }
            if (jobs == null)
            {
                throw new ArgumentNullException("jobs");
            }

            InitializeComponent();

            // Update app icon.
            this.Icon = Properties.Resources.App;
            
            Text = "Edit Job";

            _isLoading = true;
            _config.Copy(config);
            _currentJobIndex = index;
            _jobs = jobs;
            _job.Copy(_jobs[_currentJobIndex]);

            // Fill in dialog with job values.
            buttonBrowseVideoSource.Visible = false;
            textBoxVideoInput.Text = _job.SourceFilename;
            textBoxVideoOutput.Text = _job.BaseFilename;
            checkBoxAnimation.Checked = _job.IsAnimation;
            checkBoxProcessingOverride.Checked = _job.ProcessingOverrideEnabled;
            checkBoxTrim.Checked = _job.Trim;
            if (_job.DisplayAspectRatio == FicSprout.Bacicworx.Media.VideoAspectRatio.Aspect_1_33)
            {
                comboBoxAspect.SelectedIndex = 0;
            }
            if (_job.DisplayAspectRatio == FicSprout.Bacicworx.Media.VideoAspectRatio.Aspect_1_78)
            {
                comboBoxAspect.SelectedIndex = 1;
            }
            comboBoxCropAspectRatio.Items.AddRange(FicSprout.Bacicworx.Media.Utility.VideoAspectRatioNames);
            comboBoxCropAspectRatio.Text = FicSprout.Bacicworx.Media.Utility.ConvertVideoAspectRatioToName(_job.CropAspectRatio);
            comboBoxCropMode.Items.AddRange(Utility.CropModeNames);
            comboBoxCropMode.Text = Utility.ConvertCropModeToName(_job.Crop);
            comboBoxProcessingOverride.Text = FicSprout.Bacicworx.Media.Utility.ConvertVideoProcessingTypeToName(_job.ProcessingOverride);
            comboBoxProcessingOverride.Items.AddRange(FicSprout.Bacicworx.Media.Utility.VideoProcessingTypeNames);
            SetTrimLabel(_job.TrimStartTimecode, _job.TrimEndTimecode);
            numericUpDownBottom.Value = _job.CropBottom;
            numericUpDownLeft.Value = _job.CropLeft;
            numericUpDownRight.Value = _job.CropRight;
            numericUpDownTop.Value = _job.CropTop;

            listViewAudioTracks.Items.Clear();
            for (int i = 0; i < _job.AudioTracks.Count; i++)
            {
                ListViewItem item = new ListViewItem(System.IO.Path.GetFileNameWithoutExtension(_job.AudioTracks[i].Filename));
                item.SubItems.Add(_job.AudioTracks[i].Delay.ToString());
                item.SubItems.Add(Utility.ConvertAudioFormatToName(_job.AudioTracks[i].Format));
                item.SubItems.Add(Utility.ConvertAudioFormatToName(_job.AudioTracks[i].OutputFormat));
                listViewAudioTracks.Items.Add(item);
            }

            openFileDialog.InitialDirectory = System.IO.Path.GetDirectoryName(_job.SourceFilename);

            ShowVideoFormatInfo();

            UpdateUI();
            textBoxVideoInput.Focus();
            _isLoading = false;
        }

        /// <summary>
        /// Updates the trim label.
        /// </summary>
        /// <param name="start">The start timecode.</param>
        /// <param name="end">The end timecopde. A timecode of zero frames means render to the end of the video.</param>
        private void SetTrimLabel(FicSprout.Bacicworx.Media.SmpteTimecode start,
            FicSprout.Bacicworx.Media.SmpteTimecode end)
        {
            if (end.TotalFrames == 0)
            {
                labelTrimValues.Text = "[" + start.ToString() + "]  --->  [End Of Video]";
            }
            else
            {
                labelTrimValues.Text = "[" + start.ToString() + "]  --->  [" + end.ToString() + "]";
            }
        }

        /// <summary>
        /// Displays brief info about the video and updates the labelFormatInfo control.
        /// </summary>
        private void ShowVideoFormatInfo()
        {

            if (_job.VideoType == FicSprout.Bacicworx.Media.VideoType.NtscFilm ||
                _job.VideoType == FicSprout.Bacicworx.Media.VideoType.NtscHybridFilm ||
                _job.VideoType == FicSprout.Bacicworx.Media.VideoType.NtscHybridVideo ||
                _job.VideoType == FicSprout.Bacicworx.Media.VideoType.NtscVideo)
            {
                if (_job.DisplayAspectRatio == FicSprout.Bacicworx.Media.VideoAspectRatio.Aspect_1_33)
                {
                    labelFormatInfo.Text = "NTSC Fullscreen (" + _job.SourceWidth.ToString() + "x" +
                        _job.SourceHeight.ToString() + "),  Resize 720x544";
                    comboBoxAspect.SelectedIndex = 0;
                }
                if (_job.DisplayAspectRatio == FicSprout.Bacicworx.Media.VideoAspectRatio.Aspect_1_78)
                {
                    labelFormatInfo.Text = "NTSC Widescreen (" + _job.SourceWidth.ToString() + "x" +
                        _job.SourceHeight.ToString() + "),  Resize 864x480";
                    comboBoxAspect.SelectedIndex = 1;
                }
            }
            if (_job.VideoType == FicSprout.Bacicworx.Media.VideoType.PalVideo)
            {
                if (_job.DisplayAspectRatio == FicSprout.Bacicworx.Media.VideoAspectRatio.Aspect_1_33)
                {
                    labelFormatInfo.Text = "PAL Fullscreen (" + _job.SourceWidth.ToString() + "x" +
                        _job.SourceHeight.ToString() + "),  Resize 768x576";
                    comboBoxAspect.SelectedIndex = 0;
                }
                if (_job.DisplayAspectRatio == FicSprout.Bacicworx.Media.VideoAspectRatio.Aspect_1_78)
                {
                    labelFormatInfo.Text = "PAL Widescreen (" + _job.SourceWidth.ToString() + "x" +
                        _job.SourceHeight.ToString() + "),  Resize 1024x576";
                    comboBoxAspect.SelectedIndex = 1;
                }
            }
        }

        /// <summary>
        /// Updates the audio tracks ListView control.
        /// </summary>
        private void UpdateAudioTracksListView()
        {
            listViewAudioTracks.Items.Clear();
            for (int i = 0; i < _job.AudioTracks.Count; i++)
            {
                ListViewItem item = new ListViewItem(System.IO.Path.GetFileNameWithoutExtension(_job.AudioTracks[i].Filename));
                item.SubItems.Add(_job.AudioTracks[i].Delay.ToString());
                item.SubItems.Add(Utility.ConvertAudioFormatToName(_job.AudioTracks[i].Format));
                item.SubItems.Add(Utility.ConvertAudioFormatToName(_job.AudioTracks[i].OutputFormat));
                listViewAudioTracks.Items.Add(item);
            }
        }

        /// <summary>
        /// Updates the UI.
        /// </summary>
        private void UpdateUI()
        {
            // Disable UI controls.
            buttonOK.Enabled = false;
            checkBoxAnimation.Enabled = false;
            checkBoxProcessingOverride.Enabled = false;
            checkBoxTrim.Enabled = false;
            comboBoxAspect.Visible = false;
            comboBoxCropAspectRatio.Visible = false;
            comboBoxCropMode.Enabled = false;
            comboBoxProcessingOverride.Enabled = false;
            labelCropAspectRatio.Visible = false;
            labelCropMode.Enabled = false;
            labelCropResolution.Visible = false;
            labelFormat.Enabled = false;
            listViewAudioTracks.Enabled = false;
            numericUpDownBottom.Visible = false;
            numericUpDownLeft.Visible = false;
            numericUpDownRight.Visible = false;
            numericUpDownTop.Visible = false;
            toolStripButtonAddAudioTrack.Enabled = false;
            toolStripButtonMoveAudioTrackDown.Enabled = false;
            toolStripButtonMoveAudioTrackUp.Enabled = false;
            toolStripButtonRemoveAudioTrack.Enabled = false;
            toolStripButtonEditAudioTrack.Enabled = false;

            if (textBoxVideoInput.Text.Length > 0)
            {
                buttonOK.Enabled = true;
                checkBoxAnimation.Enabled = true;
                checkBoxProcessingOverride.Enabled = true;
                checkBoxTrim.Enabled = true;
                comboBoxAspect.Visible = true;
                comboBoxCropMode.Enabled = true;
                labelCropMode.Enabled = true;
                labelFormat.Enabled = true;
                listViewAudioTracks.Enabled = true;
                toolStripButtonAddAudioTrack.Enabled = true;
                toolStripButtonMoveAudioTrackDown.Enabled = true;
                toolStripButtonMoveAudioTrackUp.Enabled = true;
                toolStripButtonRemoveAudioTrack.Enabled = true;

                if (checkBoxProcessingOverride.Checked)
                {
                    comboBoxProcessingOverride.Enabled = true;
                }

                if (comboBoxCropMode.Text == "Aspect")
                {
                    comboBoxCropAspectRatio.Visible = true;
                    labelCropAspectRatio.Visible = true;
                    labelCropResolution.Visible = true;

                    // Update crop resolution.
                    Int32 videoHeight = 0;
                    Int32 videoWidth = 0;

                    Utility.ComputeJobCroppedVideoResolution(_job, ref videoHeight, ref videoWidth);

                    if (videoHeight > 0 && videoWidth > 0)
                    {
                        labelCropResolution.Text = "[ " + videoWidth.ToString() + " x " + videoHeight.ToString() + " ]";
                    }
                }

                if (comboBoxCropMode.Text == "Manual")
                {
                    labelCropResolution.Visible = true;
                    numericUpDownBottom.Visible = true;
                    numericUpDownLeft.Visible = true;
                    numericUpDownRight.Visible = true;
                    numericUpDownTop.Visible = true;

                    // Update crop resolution.
                    labelCropResolution.Text = "[ " + (_job.ResizeWidth - _job.CropLeft - _job.CropRight).ToString() + " x " +
                       (_job.ResizeHeight - _job.CropBottom - _job.CropTop).ToString() + " ]";
                }

                if (listViewAudioTracks.Items.Count > 0 && listViewAudioTracks.SelectedIndices.Count == 1)
                {
                    toolStripButtonEditAudioTrack.Enabled = true;
                }
            }
        }

        #endregion

        #region Events

        private void buttonBrowseVideoSource_Click(object sender, EventArgs e)
        {
            // file exists?
            openFileDialog.Title = "Open Video";
            openFileDialog.Filter = Utility.SupporteVideoDialogFilters;
            openFileDialog.Multiselect = false;
            labelFormatInfo.Text = string.Empty;

            // Cancel? No filename?
            if (openFileDialog.ShowDialog() == System.Windows.Forms.DialogResult.Cancel ||
                string.IsNullOrEmpty(openFileDialog.FileName))
            {
                return;
            }
            // File is zero-length?
            if (new FileInfo(openFileDialog.FileName).Length == 0)
            {
                MessageBox.Show("Cannot add an empty video.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            // Update job info.
            Utility.PreviewIndexVideo(openFileDialog.FileName, _job, _config);
            Utility.LoadAudioTracks(_job, _config);

            textBoxVideoInput.Text = _job.SourceFilename;
            textBoxVideoOutput.Text = _job.BaseFilename;
            comboBoxCropAspectRatio.Text = FicSprout.Bacicworx.Media.Utility.ConvertVideoAspectRatioToName(_job.CropAspectRatio);
            ShowVideoFormatInfo();

            UpdateAudioTracksListView();
            UpdateUI();
        }

        private void buttonBrowseVideoSource_MouseDown(object sender, MouseEventArgs e)
        {
            buttonBrowseVideoSource.Image = imageList1.Images[1];
        }

        private void buttonBrowseVideoSource_MouseUp(object sender, MouseEventArgs e)
        {
            buttonBrowseVideoSource.Image = imageList1.Images[0];
        }

        private void checkBoxAnimation_CheckedChanged(object sender, EventArgs e)
        {
            if (!_isLoading)
            {
                _job.IsAnimation = checkBoxAnimation.Checked;
            }

            checkBoxAnimation.Checked = _job.IsAnimation;
        }

        private void checkBoxProcessingOverride_CheckedChanged(object sender, EventArgs e)
        {
            if (!_isLoading)
            {
                _job.ProcessingOverrideEnabled = checkBoxProcessingOverride.Checked;
            }

            UpdateUI();
        }

        private void checkBoxTrim_CheckedChanged(object sender, EventArgs e)
        {
            if (!_isLoading)
            {
                _job.Trim = checkBoxTrim.Checked;
            }

            labelTrimValues.Visible = checkBoxTrim.Checked;
        }

        private void comboBoxAspect_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (!_isLoading)
            {
                if (comboBoxAspect.SelectedIndex == 0)
                {
                    _job.DisplayAspectRatio = FicSprout.Bacicworx.Media.VideoAspectRatio.Aspect_1_33;
                }
                if (comboBoxAspect.SelectedIndex == 1)
                {
                    _job.DisplayAspectRatio = FicSprout.Bacicworx.Media.VideoAspectRatio.Aspect_1_78;
                }

                _job.CropAspectRatio = _job.DisplayAspectRatio;
                Utility.ComputeVideoResizeValues(_job);
            }

            comboBoxCropAspectRatio.Text = FicSprout.Bacicworx.Media.Utility.ConvertVideoAspectRatioToName(_job.CropAspectRatio);
            ShowVideoFormatInfo();
            UpdateUI();
        }

        private void comboBoxCropAspectRatio_TextChanged(object sender, EventArgs e)
        {
            if (!_isLoading)
            {

                _job.CropAspectRatio = FicSprout.Bacicworx.Media.Utility.ConvertVideoAspectRatioFromName(comboBoxCropAspectRatio.Text);
            }

            UpdateUI();
        }

        private void comboBoxCropMode_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (!_isLoading)
            {
                _job.Crop = Utility.ConvertCropModeFromName(comboBoxCropMode.Text);
            }

            UpdateUI();
        }

        private void comboBoxOverride_TextChanged(object sender, EventArgs e)
        {
            if (!_isLoading)
            {
                _job.ProcessingOverride = FicSprout.Bacicworx.Media.Utility.ConvertVideoProcessingTypeFromName(comboBoxProcessingOverride.Text);
            }
        }

        private void JobDialog_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (DialogResult == System.Windows.Forms.DialogResult.Cancel)
            {
                return;
            }

            // If manual crop values are not mod 16, artifacts can occur in encoded video.
            if (_job.Crop == CropMode.Manual)
            {
                if ((_job.CropLeft + _job.CropRight) % 16 != 0 || (_job.CropTop + _job.CropBottom) % 16 != 0)
                {
                    MessageBox.Show("Crop Left+Right or Top+Bottom is not a multiple of 16.\n" +
                        "Artifacting can occur in encoded video.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);

                    e.Cancel = true;
                    return;
                }
            }

            // Adding/editing a job and the output filename is already used by another job?
            // For existing jobs, ignore if the found job is this job.
            Int32 index = Utility.IndexOfJobOutputFilename(_job.SourceFilename, _job.BaseFilename, _jobs);
            if (index != -1 && index != _currentJobIndex)
            {
                MessageBox.Show("The output filename is already used by another\njob. Change the output filename.",
                     "Duplicate Filename", MessageBoxButtons.OK, MessageBoxIcon.Error);

                e.Cancel = true;
                return;
            }

            // Adding a job and the source filename is already in the jobs list?
            index = Utility.IndexOfJobSourceFilename(_job.SourceFilename, _jobs);
            if (_currentJobIndex == -1 && index != -1 &&
                MessageBox.Show("The video source is already in the jobs list.\n\n" +
                "Add it anyway?", "Duplicate Filename", MessageBoxButtons.YesNo, MessageBoxIcon.Question) ==
                System.Windows.Forms.DialogResult.No)
            {

                e.Cancel = true;
                return;
            }

            if (Text == "Add Job")
            {
                // Add the new job to the list.
                _jobs.Add(_job);
            }
            else
            {
                // Update the existing job.
                _jobs[_currentJobIndex].Copy(_job);
            }
        }

        private void labelTrimValues_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            JobTrimDialog dialog = new JobTrimDialog(_job.TrimStartTimecode, _job.TrimEndTimecode);

            if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                _job.TrimStartTimecode = new FicSprout.Bacicworx.Media.SmpteTimecode(dialog.TrimStartTimecode);
                _job.TrimEndTimecode = new FicSprout.Bacicworx.Media.SmpteTimecode(dialog.TrimEndTimecode);

                SetTrimLabel(_job.TrimStartTimecode, _job.TrimEndTimecode);
            }

            dialog.Close();
            dialog.Dispose();
        }

        private void listViewAudioTracks_SelectedIndexChanged(object sender, EventArgs e)
        {
            toolStripButtonEditAudioTrack.Enabled = false;
            if (listViewAudioTracks.Items.Count > 0 && listViewAudioTracks.SelectedIndices.Count == 1)
            {
                toolStripButtonEditAudioTrack.Enabled = true;
            }
        }

        private void numericUpDownBottom_ValueChanged(object sender, EventArgs e)
        {
            if (!_isLoading)
            {
                _job.CropBottom = (Int32)numericUpDownBottom.Value;
                _job.CropLeft = (Int32)numericUpDownLeft.Value;
                _job.CropRight = (Int32)numericUpDownRight.Value;
                _job.CropTop = (Int32)numericUpDownTop.Value;
            }

            UpdateUI();
        }

        private void textBoxVideoOutput_TextChanged(object sender, EventArgs e)
        {
            if (!_isLoading)
            {
                _job.BaseFilename = System.IO.Path.GetFileNameWithoutExtension(textBoxVideoOutput.Text);
            }
        }

        private void toolStripButtonAddAudioTrack_Click(object sender, EventArgs e)
        {
            // file exists?
            openFileDialog.Title = "Add Audio Tracks";
            openFileDialog.Filter = Utility.SupportedAudioDialogFilters;
            openFileDialog.FilterIndex = 2;
            openFileDialog.Multiselect = true;

            DialogResult result = System.Windows.Forms.DialogResult.None;

            try
            {
                result = openFileDialog.ShowDialog();
            }
            catch
            {
                // If too many files are selected, the dialog will throw an exception.
                MessageBox.Show("Too many files selected. Please select fewer files and try again.");
                return;
            }

            if (result == System.Windows.Forms.DialogResult.Cancel)
            {
                return;
            }


            // File is zero-length? Then do not add it.
            if (new FileInfo(openFileDialog.FileName).Length == 0)
            {
                MessageBox.Show("Cannot add an empty audio track.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            Utility.AddAudioTracks(_job, _config, openFileDialog.FileNames);
            UpdateAudioTracksListView();
            UpdateUI();
        }

        private void toolStripButtonEditAudioTrack_Click(object sender, EventArgs e)
        {
            if (listViewAudioTracks.SelectedIndices.Count != 1)
            {
                return;
            }

            EditAudioTrackDialog dialog = new EditAudioTrackDialog(
                _job.AudioTracks[listViewAudioTracks.SelectedIndices[0]].Format,
                _job.AudioTracks[listViewAudioTracks.SelectedIndices[0]].OutputFormat,
                _config.ContainerFormat,
                _job.AudioTracks[listViewAudioTracks.SelectedIndices[0]].Delay,
                _job.AudioTracks[listViewAudioTracks.SelectedIndices[0]].DynamicRangeCompression,
                _job.AudioTracks[listViewAudioTracks.SelectedIndices[0]].Normalize);

            if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                _job.AudioTracks[listViewAudioTracks.SelectedIndices[0]].Delay = dialog.AudioDelay;
                _job.AudioTracks[listViewAudioTracks.SelectedIndices[0]].DynamicRangeCompression = dialog.AudioDynamicRangeCompression;
                _job.AudioTracks[listViewAudioTracks.SelectedIndices[0]].Normalize = dialog.AudioNormalize;
                _job.AudioTracks[listViewAudioTracks.SelectedIndices[0]].OutputFormat = dialog.AudioOutputFormat;

                ListViewItem item = listViewAudioTracks.Items[listViewAudioTracks.SelectedIndices[0]];
                item.SubItems[1].Text = _job.AudioTracks[listViewAudioTracks.SelectedIndices[0]].Delay.ToString();
                item.SubItems[2].Text = Utility.ConvertAudioFormatToName(_job.AudioTracks[listViewAudioTracks.SelectedIndices[0]].Format);
                item.SubItems[3].Text = Utility.ConvertAudioFormatToName(_job.AudioTracks[listViewAudioTracks.SelectedIndices[0]].OutputFormat);
            }

            dialog.Close();
            dialog.Dispose();
        }

        private void toolStripButtonMoveAudioTrackDown_Click(object sender, EventArgs e)
        {
            if (listViewAudioTracks.SelectedIndices.Count == 1 &&
                listViewAudioTracks.SelectedIndices[0] < listViewAudioTracks.Items.Count - 1)
            {
                Int32 index = listViewAudioTracks.SelectedIndices[0];

                AudioTrackInfo info = new AudioTrackInfo();
                info.Copy(_job.AudioTracks[index + 1]);

                _job.AudioTracks[index + 1].Copy(_job.AudioTracks[index]);
                _job.AudioTracks[index].Copy(info);

                listViewAudioTracks.Items[index + 1].SubItems[0].Text = System.IO.Path.GetFileNameWithoutExtension(
                    _job.AudioTracks[index + 1].Filename);
                listViewAudioTracks.Items[index + 1].SubItems[1].Text = _job.AudioTracks[index + 1].Delay.ToString();
                listViewAudioTracks.Items[index + 1].SubItems[2].Text = Utility.ConvertAudioFormatToName(_job.AudioTracks[index + 1].Format);
                listViewAudioTracks.Items[index + 1].SubItems[3].Text = Utility.ConvertAudioFormatToName(_job.AudioTracks[index + 1].OutputFormat);

                listViewAudioTracks.Items[index].SubItems[0].Text = System.IO.Path.GetFileNameWithoutExtension(
                    _job.AudioTracks[index].Filename);
                listViewAudioTracks.Items[index].SubItems[1].Text = _job.AudioTracks[index].Delay.ToString();
                listViewAudioTracks.Items[index].SubItems[2].Text = Utility.ConvertAudioFormatToName(_job.AudioTracks[index].Format);
                listViewAudioTracks.Items[index].SubItems[3].Text = Utility.ConvertAudioFormatToName(_job.AudioTracks[index].OutputFormat);

                listViewAudioTracks.SelectedIndices.Clear();
                listViewAudioTracks.SelectedIndices.Add(index + 1);
            }
        }

        private void toolStripButtonMoveAudioTrackUp_Click(object sender, EventArgs e)
        {
            if (listViewAudioTracks.SelectedIndices.Count == 1 &&
                listViewAudioTracks.SelectedIndices[0] > 0)
            {
                Int32 index = listViewAudioTracks.SelectedIndices[0];

                AudioTrackInfo info = new AudioTrackInfo();
                info.Copy(_job.AudioTracks[index - 1]);

                _job.AudioTracks[index - 1].Copy(_job.AudioTracks[index]);
                _job.AudioTracks[index].Copy(info);

                listViewAudioTracks.Items[index - 1].SubItems[0].Text = System.IO.Path.GetFileNameWithoutExtension(
                    _job.AudioTracks[index - 1].Filename);
                listViewAudioTracks.Items[index - 1].SubItems[1].Text = _job.AudioTracks[index - 1].Delay.ToString();
                listViewAudioTracks.Items[index - 1].SubItems[2].Text = Utility.ConvertAudioFormatToName(_job.AudioTracks[index - 1].Format);
                listViewAudioTracks.Items[index - 1].SubItems[3].Text = Utility.ConvertAudioFormatToName(_job.AudioTracks[index - 1].OutputFormat);

                listViewAudioTracks.Items[index].SubItems[0].Text = System.IO.Path.GetFileNameWithoutExtension(
                    _job.AudioTracks[index].Filename);
                listViewAudioTracks.Items[index].SubItems[1].Text = _job.AudioTracks[index].Delay.ToString();
                listViewAudioTracks.Items[index].SubItems[2].Text = Utility.ConvertAudioFormatToName(_job.AudioTracks[index].Format);
                listViewAudioTracks.Items[index].SubItems[3].Text = Utility.ConvertAudioFormatToName(_job.AudioTracks[index].OutputFormat);

                listViewAudioTracks.SelectedIndices.Clear();
                listViewAudioTracks.SelectedIndices.Add(index - 1);
            }
        }

        private void toolStripButtonRemoveAudioTrack_Click(object sender, EventArgs e)
        {
            if (listViewAudioTracks.SelectedIndices.Count == 1 && listViewAudioTracks.SelectedIndices[0] != -1)
            {
                _job.AudioTracks.RemoveAt(listViewAudioTracks.SelectedIndices[0]);
                listViewAudioTracks.Items.RemoveAt(listViewAudioTracks.SelectedIndices[0]);
            }
        }

        #endregion
    }
}
