using System;
using System.Collections.Generic;
using System.Windows.Forms;
using SepehrFlightApiSampleClient.Booking.WebApi;
using SepehrFlightApiSampleClient.Booking.WinForms.Book.InMemoryDatabase.BookedPnrs.Repository;
using SepehrFlightApiSampleClient.Booking.WinForms.Book.PassengerUserControls;
using SepehrFlightApiSampleClient.BuiltinTypeExtensions;
using BookRequestModel = Sepehr.ApiGateway.Partners.Contracts.Flight.Booking.V9.Book.RequestModel;

namespace SepehrFlightApiSampleClient.Booking.WinForms.Book
{
    public partial class BookForm : Form
    {
        private readonly MainForm _mainForm;
        private readonly BookCommand.Command _command;
        private readonly int? _departureLockId;
        private readonly int? _returningLockId;

        public BookForm(
            MainForm mainForm,
            BookCommand.Command command,
            int? departureLockId,
            int? returningLockId)
        {
            _mainForm = mainForm;
            _command = command;
            _departureLockId = departureLockId;
            _returningLockId = returningLockId;
            InitializeComponent();

            SyncSelectedFlight();
        }

        private void SyncSelectedFlight()
        {
            txtBookYourLocalInventoryPnr.Text = Guid.NewGuid().ToString();

            txtDepartureFlightNumber.Text = _command.Departure.FlightNumber;
            dtpDepartureFlightDate.Value = _command.Departure.DepartureDateTime.ParseFlightDate();
            txtDepartureOrigin.Text = _command.Departure.OriginIataCode;
            txtDepartureDestination.Text = _command.Departure.DestinationIataCode;
            txtDepartureFareName.Text = _command.Departure.FareName;
            txtDepartureLockId.Text = _departureLockId?.ToString();

            if (_command.Returning != null)
            {
                txtReturningFlightNumber.Text = _command.Returning.FlightNumber;
                dtpReturningFlightDate.Value = _command.Returning.DepartureDateTime.ParseFlightDate();
                txtReturningOrigin.Text = _command.Returning.OriginIataCode;
                txtReturningDestination.Text = _command.Returning.DestinationIataCode;
                txtReturningFareName.Text = _command.Returning.FareName;
                txtReturningLockId.Text = _returningLockId?.ToString();
            }
            else
            {
                txtReturningFlightNumber.Visible = false;
                dtpReturningFlightDate.Visible = false;
                txtReturningOrigin.Visible = false;
                txtReturningDestination.Visible = false;
                txtReturningFareName.Visible = false;
                txtReturningLockId.Visible = false;
            }
            

            passengersPanel.Controls.Clear();
            var adultUserControl = new AdultUserControl(
                GetSingleAdultPayable(),
                isInternationalRoute: RouteService.IsInternationalRoute(
                    _command.Departure.OriginIataCode, 
                    _command.Departure.DestinationIataCode),
                passengersPanel: passengersPanel);
            adultUserControl.Dock = DockStyle.Top;
            passengersPanel.Controls.Add(adultUserControl);
        }

        private void btnBook_Click(object sender, EventArgs e)
        {
            var adults = new List<BookRequestModel.Passenger>();
            foreach (Control passengerUserControl in passengersPanel.Controls)
            {
                var adultUserControl = passengerUserControl as AdultUserControl;
                if (adultUserControl != null)
                {
                    adults.Add(adultUserControl.GetPassengerInfo());
                }
            }

            var childs = new List<BookRequestModel.Passenger>();
            foreach (Control passengerUserControl in passengersPanel.Controls)
            {
                var childUserControl = passengerUserControl as ChildUserControl;
                if (childUserControl != null)
                {
                    childs.Add(childUserControl.GetPassengerInfo());
                }
            }

            var infants = new List<BookRequestModel.Passenger>();
            foreach (Control passengerUserControl in passengersPanel.Controls)
            {
                var infantUserControl = passengerUserControl as InfantUserControl;
                if (infantUserControl != null)
                {
                    infants.Add(infantUserControl.GetPassengerInfo());
                }
            }

            var request = new BookRequestModel.Request
            {
                UserName = _mainForm.txtUsername.Text,
                Password = _mainForm.txtPassword.Text,
                AdultPassengers = adults,
                ChildPassengers = childs,
                InfantPassengers = infants,
                MobileNumber = txtBookMobileNumber.Text,
                Email = txtBookEmail.Text,
                YourLocalInventoryPnr = txtBookYourLocalInventoryPnr.Text,
                TotalPayable = 0
            };

            if (
                _command.Departure != null
                &&
                _command.Returning != null)
            {
                request.DepartureSegment = new BookRequestModel.FlightSegment
                {
                    OriginIataCode = txtDepartureOrigin.Text,
                    DestinationIataCode = txtDepartureDestination.Text,
                    DepartureDateTime = dtpDepartureFlightDate.Value.ToString("yyyy-MM-dd HH:mm"),
                    FlightNumber = txtDepartureFlightNumber.Text,
                    FareName = txtDepartureFareName.Text,
                    LockId = string.IsNullOrEmpty(txtDepartureLockId.Text)
                        ? (int?)null
                        : Convert.ToInt32(txtDepartureLockId.Text)
                };

                request.ReturningSegment = new BookRequestModel.FlightSegment
                {
                    OriginIataCode = txtReturningOrigin.Text,
                    DestinationIataCode = txtReturningDestination.Text,
                    DepartureDateTime = dtpReturningFlightDate.Value.ToString("yyyy-MM-dd HH:mm"),
                    FlightNumber = txtReturningFlightNumber.Text,
                    FareName = txtReturningFareName.Text,
                    LockId = string.IsNullOrEmpty(txtReturningLockId.Text)
                        ? (int?)null
                        : Convert.ToInt32(txtReturningLockId.Text)
                };

                request.TotalPayable +=
                    _command.Departure.AdultPayable * adults.Count
                    +
                    _command.Departure.ChildPayable * childs.Count
                    +
                    _command.Departure.InfantPayable * infants.Count
                    +
                    _command.Returning.AdultPayable * adults.Count
                    +
                    _command.Returning.ChildPayable * childs.Count
                    +
                    _command.Returning.InfantPayable * infants.Count;
            }
            else
            {
                request.DepartureSegment = new BookRequestModel.FlightSegment
                {
                    OriginIataCode = txtDepartureOrigin.Text,
                    DestinationIataCode = txtDepartureDestination.Text,
                    DepartureDateTime = dtpDepartureFlightDate.Value.ToString("yyyy-MM-dd HH:mm"),
                    FlightNumber = txtDepartureFlightNumber.Text,
                    FareName = txtDepartureFareName.Text,
                    LockId = string.IsNullOrEmpty(txtDepartureLockId.Text)
                        ? (int?)null
                        : Convert.ToInt32(txtDepartureLockId.Text)
                };

                request.TotalPayable +=
                    _command.Departure.AdultPayable * adults.Count
                    +
                    _command.Departure.ChildPayable * childs.Count
                    +
                    _command.Departure.InfantPayable * infants.Count;
            }

            var response = BookApi.Post(_mainForm.txtUrl.Text, request);

            var repositoryModel = ApiResponseModelToRepositoryModelConvertor.Convert(response);
            BookedPnrRepository.Add(repositoryModel);

            MessageBox.Show($"Done :) Your PNR is {response.Pnr}");
        }


        private void btnAddAdult_Click(object sender, EventArgs e)
        {
            var adultUserControl = new AdultUserControl(
                GetSingleAdultPayable(),
                isInternationalRoute: RouteService.IsInternationalRoute(
                    _command.Departure.OriginIataCode, 
                    _command.Departure.DestinationIataCode),
                passengersPanel: passengersPanel);
            adultUserControl.Dock = DockStyle.Top;
            passengersPanel.Controls.Add(adultUserControl);
        }

        private void btnAddChild_Click(object sender, EventArgs e)
        {
            var childUserControl = new ChildUserControl(
                GetSingleChildPayable(),
                isInternationalRoute: RouteService.IsInternationalRoute(
                    _command.Departure.OriginIataCode, 
                    _command.Departure.DestinationIataCode),
                passengersPanel: passengersPanel);
            childUserControl.Dock = DockStyle.Bottom;
            passengersPanel.Controls.Add(childUserControl);
        }

        private void btnAddInfant_Click(object sender, EventArgs e)
        {
            var infantUserControl = new InfantUserControl(
                GetSingleInfantPayable(),
                isInternationalRoute: RouteService.IsInternationalRoute(
                    _command.Departure.OriginIataCode, 
                    _command.Departure.DestinationIataCode),
                passengersPanel: passengersPanel);
            infantUserControl.Dock = DockStyle.Bottom;
            passengersPanel.Controls.Add(infantUserControl);
        }

        private decimal GetSingleAdultPayable()
        {
            if (
                _command.Departure != null
                &&
                _command.Returning != null)
            {
                return 
                    _command.Departure.AdultPayable 
                    + 
                    _command.Returning.AdultPayable;
            }
            else
            {
                return _command.Departure.AdultPayable;
            }
        }

        private decimal GetSingleChildPayable()
        {
            if (
                _command.Departure != null
                &&
                _command.Returning != null)
            {
                return 
                    _command.Departure.ChildPayable 
                    + 
                    _command.Returning.ChildPayable;
            }
            else
            {
                return _command.Departure.ChildPayable;
            }
        }

        private decimal GetSingleInfantPayable()
        {
            if (
                _command.Departure != null
                &&
                _command.Returning != null)
            {
                return 
                    _command.Departure.InfantPayable 
                    + 
                    _command.Returning.InfantPayable;
            }
            else
            {
                return _command.Departure.InfantPayable;
            }
        }
    }
}
