using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using SepehrHotelApiSampleClient.Availability.SearchByCityAndDateAndGuests.WebApi;
using SepehrHotelApiSampleClient.Booking.Book.WinForms;
using RequestModel = Sepehr.ApiGateway.Partners.Contracts.Hotel.Availability.V4.SearchByCityAndDateAndGuests.RequestModel;
using ResponseModel = Sepehr.ApiGateway.Partners.Contracts.Hotel.Availability.V4.SearchByCityAndDateAndGuests.ResponseModel;
using ViewModel = SepehrHotelApiSampleClient.Availability.SearchByCityAndDateAndGuests.WinForms.ViewModels;
using LockRequestModel = Sepehr.ApiGateway.Partners.Contracts.Hotel.Booking.V5.Lock.RequestModel;
using System.Drawing;
using SepehrHotelApiSampleClient.BuiltinTypeExtensions;

namespace SepehrHotelApiSampleClient.Availability.SearchByCityAndDateAndGuests.WinForms
{
    public partial class SearchByCityAndDateAndGuestsForm : Form
    {
        private readonly MainForm _mainForm;

        private List<ResponseModel.HotelOption> _hotelList = new List<ResponseModel.HotelOption>();

        private List<RequestModel.Room> _requestRoomList = new List<RequestModel.Room>()
        {
            new RequestModel.Room
            {
                AdultCount = 2,
                ChildAgeList = new List<byte>()
            }
        };

        public SearchByCityAndDateAndGuestsForm(MainForm mainForm)
        {
            _mainForm = mainForm;
            InitializeComponent();

            dtpCheckinDate.Value = DateTime.Now.AddDays(1);
            dtpCheckoutDate.Value = DateTime.Now.AddDays(4);



            gridPackageList.Visible = false;
            gridPackageList.AutoGenerateColumns = false;
            gridPackageList.Columns.Clear();
            gridPackageList.CellClick += gridPackageList_CellClick;
            gridPackageList.RowTemplate.Height = 90;

            var column = new DataGridViewButtonColumn();
            column.AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
            gridPackageList.Columns.Add(column);

            DataGridViewButtonColumn button = new DataGridViewButtonColumn();
            button.Name = "Lock";
            button.HeaderText = "Lock";
            button.Text = "Lock";
            button.UseColumnTextForButtonValue = true;
            button.Width = 60;
            button.DefaultCellStyle.Padding = new Padding(0, 30, 10, 30);
            button.DefaultCellStyle.BackColor = Color.LightGray;
            this.gridPackageList.Columns.Add(button);
        }

        private void btnSearch_Click(object sender, EventArgs e)
        {
            try
            {
                btnSearch.Enabled = false;

                var request = new RequestModel.Request
                {
                    Username = _mainForm.txtUsername.Text,
                    Password = _mainForm.txtPassword.Text,
                    CityIataCode = txtCityIataCode.Text,
                    CheckinDate = dtpCheckinDate.Value.ToString("yyyy-MM-dd"),
                    CheckoutDate = dtpCheckoutDate.Value.ToString("yyyy-MM-dd"),
                    RoomList = _requestRoomList,
                    HotelSepehrGlobalId = GetHotelSepehrGlobalId(),
                };


                var response = SearchByCityAndDateAndGuestsApi.Post(_mainForm.txtUrl.Text, request);
                _hotelList = response.HotelOptionList;



                gridPackageList.Visible = true;
                gridPackageList.DataSource = _hotelList
                    .ConvertAll(x => new ViewModel.HotelOption(x, response.CurrencyCode));
            }
            finally
            {
                btnSearch.Enabled = true;
            }
        }

        private int? GetHotelSepehrGlobalId()
        {
            if (string.IsNullOrWhiteSpace(txtHotelSepehrGlobalId.Text))
            {
                return (int?)null;
            }

            return Convert.ToInt32(txtHotelSepehrGlobalId.Text);
        }

        private void gridPackageList_CellClick(object sender, DataGridViewCellEventArgs e)
        {
            if (e.ColumnIndex != 1)
            {
                return;
            }

            var package = ((List<ViewModels.HotelOption>)gridPackageList.DataSource)[e.RowIndex];

            var roomList = GetRoomsForLockRequest();

            var lockRequest = new LockRequestModel.Request
            {
                Username = _mainForm.txtUsername.Text,
                Password = _mainForm.txtPassword.Text,
                CheckinDate = dtpCheckinDate.Value.ToString("yyyy-MM-dd"),
                CheckoutDate = dtpCheckoutDate.Value.ToString("yyyy-MM-dd"),
                TotalPayable = package.TotalNetPrice,
                RoomList = package
                    .RoomTypeList
                    .ConvertAll(x => new LockRequestModel.Room
                    {
                        RoomTypeSepehrGlobalId = x.SepehrGlobalId,
                        BoardTypeCode = x.BoardTypeCode,
                        AdultCount = x.AdultCount,
                        ChildAgeList = x.ChildAgeList,
                    }),
            };

            var lockResponse = Booking.Lock.WebApi.LockApi.Post(
                _mainForm.txtUrl.Text,
                lockRequest);

            var bookForm = new BookForm(
                mainForm: _mainForm,
                command: new Booking.Book.WinForms.BookCommand.Command
                {
                    CheckinDate = dtpCheckinDate.Value,
                    CheckoutDate = dtpCheckoutDate.Value,
                    TotalNetPrice_TaxIncluded = package.TotalNetPrice,
                    HotelName = package.Name,
                    RoomList = package
                        .RoomTypeList
                        .ConvertAll(x => new Booking.Book.WinForms.BookCommand.Room
                        {
                            AdultCount = x.AdultCount,
                            ChildAgeList = x.ChildAgeList,
                            RoomTypeName = x.Name,
                            BoardTypeCode = x.BoardTypeCode,
                        }),
                    LockId = lockResponse.LockId
                });

            bookForm.ShowDialog();
        }

        private List<LockRequestModel.Room> GetRoomsForLockRequest()
        {
            var result = new List<LockRequestModel.Room>();

            /*
            var roomCount = Convert.ToByte(cmbRoomCount.SelectedItem);
            for (int counter = roomCount - 1; counter >= 0; counter--)
            {
                var roomUserControl = (RoomUserControl)roomsPanel.Controls[counter];

                var requestRoom = new LockRequestModel.Room
                {
                    RoomTypeSepehrGlobalId = Convert.ToInt32(roomUserControl.cmbRoomType.SelectedValue),
                    BoardTypeCode = roomUserControl.cmbBoardType.SelectedValue.ToString(),
                    AdultCount = Convert.ToByte(roomUserControl.nudAdultCount.Value),
                    ChildAgeList = new List<byte>(),
                };

                for (int childCounter = 1; childCounter <= Convert.ToByte(roomUserControl.nudChildCount.Value); childCounter++)
                {
                    var comboboxItem = (RoomUserControl.ComboboxItem)(((ComboBox)roomUserControl.Controls[$"cmbChild{childCounter}Age"]).SelectedItem);

                    if (comboboxItem.Value == -1)
                    {
                        throw new Exception($"Please select child age");
                    }

                    requestRoom.ChildAgeList.Add(comboboxItem.ValueAsByte);
                }

                result.Add(requestRoom);
            }
            */

            return result;
        }

        private void lnkRoomAndPassengerCount_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            var roomAndPassengerCountForm = new RoomAndPassengerCountForm(_requestRoomList);

            if (roomAndPassengerCountForm.ShowDialog() == DialogResult.OK)
            {
                _requestRoomList = roomAndPassengerCountForm.GetResult();

                this.lnkRoomAndPassengerCount.Text =
                    $@"{_requestRoomList.Count} Rooms, " +
                    $@"{_requestRoomList.Sum(x => x.AdultCount)} Adult, " +
                    $@"{_requestRoomList.Sum(x => x.ChildAgeList.Count)} Child";
            }
        }

        private void gridPackageList_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
        {
            //Only paint first column and RowIndex should be >=0 to avoid rendering column header
            if (
                e.ColumnIndex != 0
                ||
                e.RowIndex < 0
                ||
                gridPackageList.DataSource == null
            )
            {
                return;
            }


            var package = ((List<ViewModels.HotelOption>)gridPackageList.DataSource)[e.RowIndex];

            PaintCell(package, e);

            //Cancel default painting using e.Handled = true
            e.Handled = true;
        }


        private void PaintCell(ViewModels.HotelOption hotel, DataGridViewCellPaintingEventArgs e)
        {
            // Erase the cell
            var backColorBrush = new SolidBrush(Color.LightGray);
            e.Graphics.FillRectangle(backColorBrush, e.CellBounds);
            backColorBrush.Dispose();



            DrawStringVertical($"{e.RowIndex + 1}", 1, 40, e);


            DrawString("Hotel", 32, 10, e);
            DrawString(hotel.Name, 80, 10, e);

            DrawString("Room type", 32, 35, e);
            DrawString(string.Join("/", hotel.RoomTypeList.ConvertAll(x => GetRoomTypeTitle(x))), 120, 35, e);

            DrawString("Amenities", 32, 60, e);
            DrawString(string.Join("     ", hotel.AmenityList.ConvertAll(x => $"{x.Name}  {x.Quantity} ")), 140, 60, e);

           

            DrawString("Gross price", 750, 11, Color.DimGray, e);
            DrawString($@"{hotel.CurrencyCode} {hotel.TotalGrossPrice.FormattedNumber()}", 850, 11, e);

            DrawString("Commision", 750, 29, Color.DimGray, e);
            DrawString($@"{hotel.CurrencyCode} {hotel.TotalCommission.FormattedNumber()}", 850, 29, e);

            DrawString("Net Price", 750, 47, Color.DimGray, e);
            DrawString($@"{hotel.CurrencyCode} {hotel.TotalNetPrice.FormattedNumber()}", 850, 47, e);

            DrawLine(Color.Gray, e);
        }

        private static string GetRoomTypeTitle(ViewModels.RoomType roomType)
        {
            var result = $"{roomType.Name} {roomType.BoardTypeCode}";

            if (roomType.ExtrabedAssignedCount > 0)
            {
                result += $" ({roomType.ExtrabedAssignedCount} Extrabed)";
            }

            return result;
        }


        private void DrawString(
            string text,
            float x,
            float y,
            DataGridViewCellPaintingEventArgs e)
        {
            DrawString(text, x, y, Color.Black, e, false);
        }

        private void DrawString(
            string text,
            float x,
            float y,
            Color drawColor,
            DataGridViewCellPaintingEventArgs e)
        {
            DrawString(text, x, y, drawColor, e, false);
        }

        private void DrawStringVertical(
            string text,
            float x,
            float y,
            DataGridViewCellPaintingEventArgs e)
        {
            DrawString(text, x, y, Color.Black, e, true);
        }

        private void DrawString(
            string text,
            float x,
            float y,
            Color drawColor,
            DataGridViewCellPaintingEventArgs e,
            bool drawVertical)
        {
            Graphics formGraphics = this.CreateGraphics();
            string drawString = text;
            Font drawFont = new Font("Tahoma", 9.25F);
            SolidBrush drawBrush = new SolidBrush(drawColor);
            StringFormat drawFormat = new StringFormat();

            if (drawVertical)
            {
                drawFormat.FormatFlags = StringFormatFlags.DirectionVertical;
            }


            e.Graphics.DrawString(
                drawString,
                drawFont,
                drawBrush,
                e.CellBounds.Left + x,
                e.CellBounds.Top + y,
                drawFormat);



            drawFont.Dispose();
            drawBrush.Dispose();
            formGraphics.Dispose();
        }

        private void DrawLine(
            Color drawColor,
            DataGridViewCellPaintingEventArgs e)
        {
            SolidBrush drawBrush = new SolidBrush(drawColor);

            e.Graphics.DrawLine(
                pen: new Pen(drawBrush),
                x1: e.CellBounds.X,
                y1: e.CellBounds.Y - 1,
                x2: e.CellBounds.Width,
                y2: e.CellBounds.Y - 1);

            drawBrush.Dispose();
        }
    }
}
