using System;
using System.Data.SQLite;
using System.Windows.Forms;

namespace BulkPrinting
{
    public partial class ReprintForm : Form
    {
        public ReprintForm()
        {
            InitializeComponent();
        }

        public string PrintDescription;
        public DateTime BatchOrderDate;
        public int UnprintedVouchers;
        public int TotalVouchers;
        public string FaceValue;
        public string VoucherTypeName;
        public string NetworkName;
        public int BatchID;
        private Boolean CanReprintThisSession;
        private int MinSeqNo;
        private int MaxSeqNo;
        private int MinPageNo;
        private int MaxPageNo;

        private void ReprintForm_Load(object sender, EventArgs e)
        {
            RadioButtonChanged();

            CanReprintThisSession =
                ((Globals.SessionMode == SessionModes.Online &&
                    Utility.CheckUserAccess(Utility.UserPermissions.CanReprintOnline)) ||
                (Globals.SessionMode == SessionModes.Offline &&
                    Utility.CheckUserAccess(Utility.UserPermissions.CanReprintOffline)));
            lblPrintDescription.Text = PrintDescription;
            lblBatchNumber.Text = BatchID.ToString();
            lblBatchOrderDate.Text = BatchOrderDate.Date.ToString("dd/MM/yyyy");
            lblTotalVouchers.Text = TotalVouchers.ToString();
            lblFaceValue.Text = FaceValue;
            lblVoucherType.Text = VoucherTypeName;
            lblNetwork.Text = NetworkName;
            using (var Command = Globals.DB.CreateCommand(
                "SELECT MIN(v.SequenceNumber), MAX(v.SequenceNumber) FROM Voucher v LEFT JOIN Logs l ON v.Id = l.VoucherId AND l.EventType = @eventtype WHERE l.VoucherId IS NOT NULL AND v.BatchId=@batchid AND Retry=0",
                new SQLiteParameter("@batchid", BatchID),
                new SQLiteParameter("@eventtype", VendorEvent.VendorEventType.PrintVoucher)))
            {
                using (SQLiteDataReader read = Command.ExecuteReader())
                {
                    read.Read();
                    MinSeqNo = int.Parse(read.GetValue(0).ToString());
                    MaxSeqNo = int.Parse(read.GetValue(1).ToString());
                }
            }

            // TODO: what if the sequence numbers are contiguous from MinSeqNo to MaxSeqNo.
            MinPageNo = 1;
            MaxPageNo = (MaxSeqNo - MinSeqNo + 20) / 20;

            numFirstSeqNum.Minimum = MinSeqNo;
            numFirstSeqNum.Maximum = MaxSeqNo;
            numLastSeqNum.Minimum = MinSeqNo;
            numLastSeqNum.Maximum = MaxSeqNo;

            numFirstPageNum.Minimum = MinPageNo;
            numFirstPageNum.Maximum = MaxPageNo;
            numLastPageNum.Minimum = MinPageNo;
            numLastPageNum.Maximum = MaxPageNo;

            lblMinSeqNo.Text = MinSeqNo.ToString();
            lblMaxSeqNo.Text = MaxSeqNo.ToString();
        }

        private void btnCancel_Click(object sender, EventArgs e)
        {
            Globals.OpenBatches.Remove(BatchID);
            this.Close();
        }

        private void btnNext_Click(object sender, EventArgs e)
        {
            int SelectedRangeStart = 0;
            int SelectedRangeEnd = 0;
            int SelectedBatchID = -1;

            decimal VoucherCount;

            if (rdoRange.Checked)
            {
                if (numFirstSeqNum.Value < MinSeqNo || numLastSeqNum.Value > MaxSeqNo)
                {
                    MessageBox.Show(String.Format("Valid sequence numbers are from {0} to {1}", MinSeqNo.ToString(), MaxSeqNo.ToString()), "Invalid print value", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                    return;
                }

                if (numFirstSeqNum.Value > numLastSeqNum.Value)
                {
                    MessageBox.Show("The first sequence number in the range must be less than or equal to the last.", "Invalid range", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                    return;
                }
                if (numLastSeqNum.Value > TotalVouchers)
                {
                    MessageBox.Show("You have a final sequence number higher than the available vouchers to print. Please reduce the last sequence number to equal to or below the total number of vouchers.", "Cannot print that many vouchers", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                    return;
                }
                SelectedBatchID = BatchID;
                SelectedRangeStart = (int)numFirstSeqNum.Value;
                SelectedRangeEnd = (int)numLastSeqNum.Value;
            }
            else if (rdoPageRange.Checked)
            {
                if (numFirstPageNum.Value < MinPageNo || numLastPageNum.Value > MaxPageNo)
                {
                    MessageBox.Show(String.Format("Valid page numbers are from {0} to {1}", MinPageNo.ToString(), MaxPageNo.ToString()), "Invalid print value", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                    return;
                }

                if (numFirstPageNum.Value > numLastPageNum.Value)
                {
                    MessageBox.Show("The first page number in the range must be less than or equal to the last.", "Invalid range", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                    return;
                }

                SelectedBatchID = BatchID;
                SelectedRangeStart = ((int)numFirstPageNum.Value - 1) * 20 + MinSeqNo;
                SelectedRangeEnd = (int)numLastPageNum.Value * 20 + MinSeqNo - 1;
                if (SelectedRangeEnd > MaxSeqNo)
                {
                    SelectedRangeEnd = MaxSeqNo;
                }
            }
            else if (rdoSerial.Checked) {
                using (var command = Globals.DB.CreateCommand("SELECT * FROM Voucher WHERE Serial=@Serial AND PrintCount>0",
                    new SQLiteParameter("@Serial", txtSerialNum.Text)))
                {
                    using (var reader = command.ExecuteReader())
                    {
                        if (reader.Read())
                        {
                            SelectedBatchID = (int)reader["BatchID"];
                            SelectedRangeStart = (int)reader["SequenceNumber"];
                            SelectedRangeEnd = SelectedRangeStart;
                        }
                    }
                }
                if (SelectedBatchID < 0) {
                    MessageBox.Show("No voucher with that serial number was found to have been printed. Please provide a previously printed voucher number or use the 'Print' function to print new vouchers.", "Cannot find printed voucher", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                    return;
                }
            }

            VoucherCount = SelectedRangeEnd - SelectedRangeStart + 1;
            decimal VoucherFaceValue = (decimal)Globals.DB.ExecuteScalar(
                "SELECT FaceValue FROM Batch WHERE Id=@id",
                new SQLiteParameter("@id", BatchID));

            int UnprintedVouchersInRange = int.Parse(Globals.DB.ExecuteScalar(
                "SELECT COUNT(v.ID) FROM Voucher v LEFT JOIN Logs l ON v.Id=l.VoucherId AND l.EventType=@event WHERE v.BatchId=@batchid AND v.SequenceNumber BETWEEN @startseq AND @endseq AND l.id IS NULL",
                new SQLiteParameter("@event", (int) VendorEvent.VendorEventType.PrintVoucher),
                new SQLiteParameter("@batchid", BatchID),
                new SQLiteParameter("@startseq", SelectedRangeStart),
                new SQLiteParameter("@endseq", SelectedRangeEnd)).ToString());

            decimal PrintedVoucherValue = (VoucherCount - UnprintedVouchersInRange) * VoucherFaceValue;
            decimal UnprintedVoucherValue = UnprintedVouchersInRange * VoucherFaceValue;

            if (Globals.SessionMode == SessionModes.Online)
            {
                if (!Utility.IsValueWithinRemainingUserLimit(UserLimits.UserLimitTypes.OnlinePrint, UnprintedVoucherValue))
                {
                    MessageBox.Show("You have selected more vouchers than your permissions allow you to print today.", "Cannot print that many vouchers", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                    return;
                }
                if (!Utility.IsValueWithinRemainingUserLimit(UserLimits.UserLimitTypes.OnlineReprint, PrintedVoucherValue))
                {
                    MessageBox.Show("You have selected more previously printed vouchers than your permissions allow you to reprint today.", "Cannot print that many vouchers", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                    return;
                }
            }
            if (Globals.SessionMode == SessionModes.Offline)
            {
                if (!Utility.IsValueWithinRemainingUserLimit(UserLimits.UserLimitTypes.OfflinePrint, UnprintedVoucherValue))
                {
                    MessageBox.Show("You have selected more vouchers than your permissions allow you to print today.", "Cannot print that many vouchers", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                    return;
                }
                if (!Utility.IsValueWithinRemainingUserLimit(UserLimits.UserLimitTypes.OfflineReprint, PrintedVoucherValue))
                {
                    MessageBox.Show("You have selected more previously printed vouchers than your permissions allow you to reprint today.", "Cannot print that many vouchers", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                    return;
                }
            }

            if (Globals.MaxPrinter.ChoosePrinter())
            {
                PrintAlignmentDialog printdialog = new PrintAlignmentDialog();
                printdialog.PrintDescription = PrintDescription;
                printdialog.BatchID = SelectedBatchID;
                printdialog.BatchOrderDate = BatchOrderDate;
                printdialog.FaceValue = FaceValue;
                printdialog.VoucherTypeName = VoucherTypeName;
                printdialog.NetworkName = NetworkName;
                printdialog.NumVouchers = null;
                printdialog.FirstSeqNo = SelectedRangeStart;
                printdialog.LastSeqNo = SelectedRangeEnd;
                printdialog.Show();
                this.Close();
            }

        }

        private void txtSerialNum_TextChanged(object sender, EventArgs e)
        {

        }

        private void RadioButtonChanged()
        {
            numFirstSeqNum.Enabled = rdoRange.Checked;
            numLastSeqNum.Enabled = rdoRange.Checked;

            numFirstPageNum.Enabled = rdoPageRange.Checked;
            numLastPageNum.Enabled = rdoPageRange.Checked;

            txtSerialNum.Enabled = rdoSerial.Checked;
        }

        private void rdoRange_CheckedChanged(object sender, EventArgs e)
        {
            RadioButtonChanged();
        }

        private void rdoPageRange_CheckedChanged(object sender, EventArgs e)
        {
            RadioButtonChanged();
        }

        private void rdoSerial_CheckedChanged(object sender, EventArgs e)
        {
            RadioButtonChanged();
        }
    }
}
