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

namespace SepehrFlightApiSampleClient.Availability.WinForms.SearchByRouteAndDate
{
    public partial class SearchByRouteAndDateForm : Form
    {
        private readonly MainForm _mainForm;
        private readonly DateRangeForm _getDifferentiallyForm;
        private List<ResponseModel.CharterFlight.FlightSegment> _charterFlights = new List<ResponseModel.CharterFlight.FlightSegment>();
        private List<ResponseModel.WebserviceFlight.FlightSegment> _webserviceFlights = new List<ResponseModel.WebserviceFlight.FlightSegment>();
        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;

            btnClearSelectedDepartureFlight.Visible = false;
            btnClearSelectedReturningFlight.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",
                FetchSupplierWebserviceFlights = chkFetchSupplierWebserviceFlights.Checked,
                OriginDestinationOptionList = new List<RequestModel.OriginDestinationOption>()
                {
                    new RequestModel.OriginDestinationOption
                    {
                        OriginIataCode = txtDepartureOriginIataCode.Text,
                        DestinationIataCode = txtDepartureDestinationIataCode.Text,
                        FlightDate = dtpDepartureDate.Value.ToString("yyyy-MM-dd"),
                    },
                },
                FetchFlighsWithBookingPolicy = chkFetchFlighsWithBookingPolicy.Checked,
            };

            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);
            _charterFlights = response.CharterFlightList;
            _webserviceFlights = response.WebserviceFlightList;

            DataBindFlightGrid();
        }

        private BindingSource _bnsFlights;
        private BindingSource _bnsFlightClasses;
        private void DataBindFlightGrid()
        {
            _bnsFlights = new BindingSource();

            var charterFlightsViewModel = _charterFlights
                .Select(f => new Flight(f))
                .ToList();

            var webserviceFlightsViewModel = _webserviceFlights
                .Select(f => new Flight(f))
                .ToList();

            var allFlightsViewModel = charterFlightsViewModel.Concat(webserviceFlightsViewModel);

            allFlightsViewModel = allFlightsViewModel
                .OrderBy(f => f.DepartureDateTime);

            _bnsFlights.DataSource = allFlightsViewModel.ToList();


            gridFlightList.DataSource = _bnsFlights;
        }

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

        public FlightClass GetCurrentFlightClassFromGrid()
        {
            if (_bnsFlights?.Current == null) return null;

            return (FlightClass)_bnsFlightClasses?.Current;
        }

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

            var flightSegment = GetCurrentFlightSegmentFromGrid();

            _bnsFlightClasses = new BindingSource();
            _bnsFlightClasses.DataSource = flightSegment.Classes;
            _bnsFlightClasses.PositionChanged += _bnsFlightClasses_PositionChanged;
            FlightClassesPositionChanged();

            gridFlightClassList.DataSource = _bnsFlightClasses;

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

        private void btnBook_Click(object sender, EventArgs e)
        {
            if (_selectedDepartureFlight == null)
            {
                MessageBox.Show("Please select at least one segment to book");
                return;
            }

            var bookCommand = CommandFactory.Create(
                _selectedDepartureFlight,
                _selectedDepartureFlightClass,
                _departureLockId,
                _selectedReturningFlight,
                _selectedReturningFlightClass,
                _returningLockId);

            var bookForm = new BookForm(
                _mainForm,
                bookCommand);

            bookForm.ShowDialog();
        }

        private void btnLock_Click(object sender, EventArgs e)
        {
            if (_selectedDepartureFlight == null)
            {
                MessageBox.Show("Please select at least one segment to lock");
                return;
            }

            var lockCommand = Booking.WinForms.Lock.LockCommand.Factory.CommandFactory.Create(
                _selectedDepartureFlight,
                _selectedDepartureFlightClass,
                _selectedReturningFlight,
                _selectedReturningFlightClass);

            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 Flight _selectedDepartureFlight;
        private FlightClass _selectedDepartureFlightClass;
        private Flight _selectedReturningFlight;
        private FlightClass _selectedReturningFlightClass;
        private void btnSelectSegmentForBook_Click(object sender, EventArgs e)
        {
            if (_selectedDepartureFlight == null)
            {
                _selectedDepartureFlight = GetCurrentFlightSegmentFromGrid();
                _selectedDepartureFlightClass = GetCurrentFlightClassFromGrid();

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

                lblSelectedDepartureFlight.Text = 
                    $"Selected departure: " +
                    $"{_selectedDepartureFlight.FlightNumber}    " +
                    $"{_selectedDepartureFlight.Origin}-{_selectedDepartureFlight.Destination}    " +
                    $"{_selectedDepartureFlight.DepartureDateTime}    " +
                    $"{_selectedDepartureFlightClass.FareName}";

                btnClearSelectedDepartureFlight.Visible = true;
            }
            else
            {
                _selectedReturningFlight = GetCurrentFlightSegmentFromGrid();
                _selectedReturningFlightClass = GetCurrentFlightClassFromGrid();

                lblSelectedReturningFlight.Text = 
                    $"Selected returning: " +
                    $"{_selectedReturningFlight.FlightNumber}    " +
                    $"{_selectedReturningFlight.Origin}-{_selectedReturningFlight.Destination}    " +
                    $"{_selectedReturningFlight.DepartureDateTime}    " +
                    $"{_selectedReturningFlightClass.FareName}";

                btnClearSelectedReturningFlight.Visible = true;
            }
        }

        private void btnClearSelectedDepartureFlight_Click(object sender, EventArgs e)
        {
            _selectedDepartureFlight = null;
            _selectedDepartureFlightClass = null;

            lblSelectedDepartureFlight.Text = $"Selected departure: ";
            btnClearSelectedDepartureFlight.Visible = false;
        }

        private void btnClearSelectedReturningFlight_Click(object sender, EventArgs e)
        {
            _selectedReturningFlight = null;
            _selectedReturningFlightClass = null;

            lblSelectedReturningFlight.Text = $"Selected returning: ";
            btnClearSelectedReturningFlight.Visible = false;
        }

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

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

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

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

            if (currentFlightClass == null) return;

            flightClassExtraInfoUserControl1.SetFlightClass(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;
            }
        }
    }
}
