using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Security.Cryptography;

namespace Sample8_PlayEncryptedVideo
{
    public partial class ProgressForm : Form
    {
        private Stream _InputStream;
        private Stream _OutputStream;
        private bool _AllowClose = false;

        private bool _cancelled = false;
        public bool Cancelled
        {
            get
            {
                return _cancelled;
            }
        }

        public ProgressForm(Stream InputStream, Stream OutputStream)
        {
            InitializeComponent();

            _InputStream = InputStream;
            _OutputStream = OutputStream;

            backgroundWorkerEncryption.RunWorkerAsync();
        }

        private void backgroundWorkerEncryption_DoWork(object sender, DoWorkEventArgs e)
        {
            if (_InputStream.Length == 0)
                return;

            TripleDESCryptoServiceProvider TDES = new TripleDESCryptoServiceProvider();

            using (BinaryWriter Writer = new BinaryWriter(_OutputStream))
            { 
                byte[] Buf = new byte[Program.ChunkSize];

                List<int> SourceChunkSizeList = new List<int>();
                List<int> EncryptedChunkSizeList = new List<int>();

                int ReadBytes;
                long nTotalReadBytes = 0;
                while ((ReadBytes = _InputStream.Read(Buf, 0, Buf.Length)) > 0)
                {
                    if (backgroundWorkerEncryption.CancellationPending)
                        break;

                    byte[] EncryptedData = Program.Encrypt(Buf, ReadBytes);
                    _OutputStream.Write(EncryptedData, 0, EncryptedData.Length);

                    SourceChunkSizeList.Add(ReadBytes);
                    EncryptedChunkSizeList.Add(EncryptedData.Length);

                    nTotalReadBytes += ReadBytes;
                    backgroundWorkerEncryption.ReportProgress((int)(nTotalReadBytes * 100 / _InputStream.Length));
                }

                foreach (int SourceChunkSize in SourceChunkSizeList)
                {
                    Writer.Write(SourceChunkSize);
                }

                foreach (int EncryptedChunkSize in EncryptedChunkSizeList)
                {
                    Writer.Write(EncryptedChunkSize);
                }

                Writer.Write((int)EncryptedChunkSizeList.Count);
            }
        }

        private void backgroundWorkerEncryption_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            progressBar.Value = e.ProgressPercentage;
        }

        private void backgroundWorkerEncryption_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            _AllowClose = true;
            Close();
        }

        private void buttonCancel_Click(object sender, EventArgs e)
        {
            buttonCancel.Enabled = false;
            _cancelled = true;
            backgroundWorkerEncryption.CancelAsync();
        }

        private void ProgressForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (!_AllowClose)
                e.Cancel = true;
        }
    }
}