using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using SepehrFlightApiSampleClient.Availability.WebApi;
using SepehrFlightApiSampleClient.Booking.WinForms.Book;
using SepehrFlightApiSampleClient.Booking.WinForms.Book.BookCommand.Factory;
using SepehrFlightApiSampleClient.Booking.WinForms.Lock;
using SepehrFlightApiSampleClient.BuiltinTypeExtensions;
using SepehrFlightApiSampleClient.BulkAvailability.WinForms.DateRange;
using RequestModel = Sepehr.ApiGateway.Partners.Contracts.Flight.Availability.V17.SearchByRouteAndDate.RequestModel;
using ResponseModel = Sepehr.ApiGateway.Partners.Contracts.Flight.Availability.V17.SearchByRouteAndDate.ResponseModel;

namespace SepehrFlightApiSampleClient.Availability.WinForms.SearchByRouteAndDate
{
    public partial class SearchByRouteAndDateForm : Form
    {
        private readonly MainForm _mainForm;
        private readonly DateRangeForm _getDifferentiallyForm;
        private List<ResponseModel.Itinerary> _itineraryList = new List<ResponseModel.Itinerary>();
        private List<ResponseModel.ClosedFlight> _closedFlightList = new List<ResponseModel.ClosedFlight>();
        private int? _departureLockId = null;
        private int? _returningLockId = null;

        public SearchByRouteAndDateForm(
            MainForm mainForm,
            DateRangeForm getDifferentiallyForm)
        {
            _mainForm = mainForm;
            _getDifferentiallyForm = getDifferentiallyForm;
            InitializeComponent();

            SyncSelectedFlight();

            gridFlightList.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
            gridFlightClassList.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;

            btnClearSelectedItinerary.Visible = false;
        }

        public void SyncSelectedFlight()
        {
            var flightSegment = _getDifferentiallyForm.GetCurrentFlightFromGrid();

            if (flightSegment != null)
            {
                txtDepartureOriginIataCode.Text = flightSegment.Origin;
                txtDepartureDestinationIataCode.Text = flightSegment.Destination;
                dtpDepartureDate.Value = flightSegment.DepartureDateTime.ParseFlightDate();
                dtpReturningDate.Value = dtpDepartureDate.Value.AddDays(1);
            }
        }

        private void btnSearch_Click(object sender, EventArgs e)
        {
            var request = new RequestModel.Request
            {
                UserName = _mainForm.txtUsername.Text,
                Password = _mainForm.txtPassword.Text,
                Language = "FA",
                FetchFlightsThatAreNotOwnedBySupplier = chkFetchFlightsThatAreNotOwnedBySupplier.Checked,
                FetchFlightsThatAreRestrictedForTour = chkFetchFlightsThatAreRestrictedForTour.Checked,
                FetchClosedFlights = chkFetchClosedFlights.Checked,
                OriginDestinationOptionList = new List<RequestModel.OriginDestinationOption>()
                {
                    new RequestModel.OriginDestinationOption
                    {
                        OriginIataCode = txtDepartureOriginIataCode.Text,
                        DestinationIataCode = txtDepartureDestinationIataCode.Text,
                        FlightDate = dtpDepartureDate.Value.ToString("yyyy-MM-dd"),
                    },
                },
            };

            if (rdoRoundtrip.Checked)
            {
                request.OriginDestinationOptionList.Add(new RequestModel.OriginDestinationOption
                {
                    OriginIataCode = txtReturningOriginIataCode.Text,
                    DestinationIataCode = txtReturningDestinationIataCode.Text,
                    FlightDate = dtpReturningDate.Value.ToString("yyyy-MM-dd"),
                });
            }

            var response = SearchByRouteAndDateApi.Post(_mainForm.txtUrl.Text, request);
            _itineraryList = response.ItineraryList;
            _closedFlightList = response.ClosedFlightList;

            DataBindFlightGrid();
        }

        private BindingSource _bnsItinerary;
        private BindingSource _bnsFlight;
        private BindingSource _bnsFlightClass;
        private void DataBindFlightGrid()
        {
            _bnsItinerary = new BindingSource();
            _bnsFlight = new BindingSource();
            _bnsFlightClass = new BindingSource();
            gridFlightList.DataSource = null;
            gridFlightClassList.DataSource = null;


            var itineraryList = new List<ViewModels.Itinerary>();

            var rowIndex = 0;
            foreach (var itinerary in _itineraryList)
            {
                itineraryList.Add(new ViewModels.Itinerary(
                    itinerary: itinerary,
                    rowIndex: ++rowIndex));
            }

            foreach (var closedFlight in _closedFlightList)
            {
                itineraryList.Add(new ViewModels.Itinerary(
                    closedFlight: closedFlight,
                    rowIndex: ++rowIndex));
            }


            _bnsItinerary.DataSource = itineraryList;

            gridItineraryList.DataSource = _bnsItinerary;
        }



        private void gridItineraryList_SelectionChanged(object sender, EventArgs e)
        {
            if (_bnsItinerary?.Current == null)
            {
                return;
            }

            var itinerary = GetCurrentItineraryFromGrid();

            var flightList = new List<ViewModels.Flight>();

            flightList.Add(itinerary.DepartureFlight);

            if (itinerary.ReturningFlight != null)
            {
                flightList.Add(itinerary.ReturningFlight);
            }

            _bnsFlight = new BindingSource();
            _bnsFlight.DataSource = flightList;


            gridFlightList.DataSource = _bnsFlight;
        }

        private void gridFlightList_SelectionChanged(object sender, EventArgs e)
        {
            if (_bnsFlight.Current == null)
            {
                return;
            }

            var flightSegment = GetCurrentFlightSegmentFromGrid();

            _bnsFlightClass = new BindingSource();
            _bnsFlightClass.DataSource = flightSegment.FlightClass;
            _bnsFlightClass.PositionChanged += BnsFlightClassPositionChanged;
            FlightClassesPositionChanged();

            gridFlightClassList.DataSource = _bnsFlightClass;

            if (flightSegment.Stop1 || flightSegment.Stop2)
            {
                btnShowStopInfo.Visible = true;
            }
            else
            {
                btnShowStopInfo.Visible = false;
            }
        }

        public ViewModels.Itinerary GetCurrentItineraryFromGrid()
        {
            return (ViewModels.Itinerary)_bnsItinerary?.Current;
        }

        public ViewModels.Flight GetCurrentFlightSegmentFromGrid()
        {
            return (ViewModels.Flight)_bnsFlight?.Current;
        }

        public ViewModels.FlightClass GetCurrentFlightClassFromGrid()
        {
            if (_bnsFlight?.Current == null)
            {
                return null;
            }

            return (ViewModels.FlightClass)_bnsFlightClass?.Current;
        }

        private void btnBook_Click(object sender, EventArgs e)
        {
            if (_selectedItinerary == null)
            {
                MessageBox.Show("Please select itinerary to book");
                return;
            }

            var bookCommand = CommandFactory.Create(
                _selectedItinerary.DepartureFlight,
                _selectedItinerary.DepartureFlight.FlightClass,
                _departureLockId,
                _selectedItinerary.ReturningFlight,
                _selectedItinerary.ReturningFlight?.FlightClass,
                _returningLockId);

            var bookForm = new BookForm(
                _mainForm,
                bookCommand);

            bookForm.ShowDialog();
        }

        private void btnLock_Click(object sender, EventArgs e)
        {
            if (_selectedItinerary == null)
            {
                MessageBox.Show("Please select itinerary to lock");
                return;
            }

            var lockCommand = Booking.WinForms.Lock.LockCommand.Factory.CommandFactory.Create(
                _selectedItinerary.DepartureFlight,
                _selectedItinerary.DepartureFlight.FlightClass,
                _selectedItinerary.ReturningFlight,
                _selectedItinerary.ReturningFlight?.FlightClass);

            var lockForm = new LockForm(
                _mainForm,
                lockCommand);

            lockForm.ShowDialog();

            _departureLockId = lockForm.GetDepartureLockId();
            _returningLockId = lockForm.GetReturningLockId();
        }

        private void btnShowStopInfo_Click(object sender, EventArgs e)
        {
            var flightSegment = GetCurrentFlightSegmentFromGrid();

            MessageBox.Show(flightSegment.GetStopData());
        }


        private ViewModels.Itinerary _selectedItinerary;
        private void btnSelectSegmentForBook_Click(object sender, EventArgs e)
        {
            _selectedItinerary = GetCurrentItineraryFromGrid();

            if (_selectedItinerary == null)
            {
                MessageBox.Show($"There no itinerary to select. Maybe you need to fetch flights first.");
                return;
            }

            lblSelectedDepartureFlight.Text =
                $"Selected departure: " +
                $"{_selectedItinerary.DepartureFlight.FlightNumber}    " +
                $"{_selectedItinerary.DepartureFlight.Origin}-{_selectedItinerary.DepartureFlight.Destination}    " +
                $"{_selectedItinerary.DepartureFlight.DepartureDateTime}    " +
                $"{_selectedItinerary.DepartureFlight.FlightClass.FareName}";

            if (_selectedItinerary.ReturningFlight != null)
            {
                lblSelectedReturningFlight.Text =
                    $"Selected returning: " +
                    $"{_selectedItinerary.ReturningFlight.FlightNumber}    " +
                    $"{_selectedItinerary.ReturningFlight.Origin}-{_selectedItinerary.ReturningFlight.Destination}    " +
                    $"{_selectedItinerary.ReturningFlight.DepartureDateTime}    " +
                    $"{_selectedItinerary.ReturningFlight.FlightClass.FareName}";
            }

            btnClearSelectedItinerary.Visible = true;
        }

        private void btnClearSelectedItinerary_Click(object sender, EventArgs e)
        {
            _selectedItinerary = null;

            lblSelectedDepartureFlight.Text = $"Selected departure: ";
            lblSelectedReturningFlight.Text = $"Selected returning: ";
            btnClearSelectedItinerary.Visible = false;
        }

        private void rdoOneway_CheckedChanged(object sender, EventArgs e)
        {
            SetReturningDate();
        }

        private void rdoRoundtrip_CheckedChanged(object sender, EventArgs e)
        {
            SetReturningDate();
        }

        private void BnsFlightClassPositionChanged(object sender, EventArgs e)
        {
            FlightClassesPositionChanged();
        }

        private void FlightClassesPositionChanged()
        {
            var currentFlightClass = GetCurrentFlightClassFromGrid();

            if (currentFlightClass == null)
            {
                return;
            }

            flightClassExtraInfoUserControl1.SetFlightClass(
                GetCurrentFlightSegmentFromGrid(),
                currentFlightClass);
        }

        private void SetReturningDate()
        {
            if (rdoOneway.Checked)
            {
                lblReturningOrigin.Visible = false;
                txtReturningOriginIataCode.Visible = false;
                lblReturningDestination.Visible = false;
                txtReturningDestinationIataCode.Visible = false;
                lblReturningDate.Visible = false;
                dtpReturningDate.Visible = false;
            }
            else
            {
                txtReturningOriginIataCode.Text = txtDepartureDestinationIataCode.Text;
                txtReturningDestinationIataCode.Text = txtDepartureOriginIataCode.Text;

                lblReturningOrigin.Visible = true;
                txtReturningOriginIataCode.Visible = true;
                lblReturningDestination.Visible = true;
                txtReturningDestinationIataCode.Visible = true;
                lblReturningDate.Visible = true;
                dtpReturningDate.Visible = true;
            }
        }
    }
}
