using ImGuiNET;
using skyscraper5.Skyscraper;
using skyscraper5.Skyscraper.Equipment;
using skyscraper5.Skyscraper.IO.CrazycatStreamReader;
using skyscraper5.Skyscraper.Scraper.Storage;
using skyscraper8.Skyscraper.Scraper.Storage;

namespace SDL2Demo.Forms
{
    internal class ConfigureTunersWindow : IRenderable
    {
        private readonly DataStorage _scraperStroage;
        private List<SatellitePositionEntity> satPositions;
        private List<LnbEntity> lnbTypes;
        private List<DishEntity> dishTypes;

        public ConfigureTunersWindow(List<TunerMetadata> tuners, DataStorage scraperStroage)
        {
            _scraperStroage = scraperStroage;
            Tuners = tuners;
            TableGuid = Guid.NewGuid().ToString();
            TableGuid2 = Guid.NewGuid().ToString();
            bool needSats = Tuners.Any(x => x.Type == STD_TYPE.STD_DVBS);
            if (needSats)
            {
                satPositions = _scraperStroage.UiSatellitesListAll();
                lnbTypes = _scraperStroage.UiLnbTypesListAll();
                dishTypes = _scraperStroage.UiDishTypesListAll();
                selectedSatListItems = new int[Tuners.Count][];
                selectedLnbListItems = new int[Tuners.Count][];
                selectedDishListItems = new int[Tuners.Count][];
                selectedDiseqcOptions = new int[Tuners.Count];
                for (int x = 0; x < Tuners.Count; x++)
                {
                    selectedDiseqcOptions[x] = Tuners[x].DiseqcType;
                    if (Tuners[x].Type == STD_TYPE.STD_DVBS)
                    {
                        selectedSatListItems[x] = new int[4];
                        selectedLnbListItems[x] = new int[4];
                        selectedDishListItems[x] = new int[4];
                        for (int y = 0; y < 4; y++)
                        {
                            int satelliteKey = Tuners[x].Satellites[y];
                            int lnbKey = Tuners[x].Lnbs[y];
                            int dishKey = Tuners[x].Dishes[y];
                            selectedSatListItems[x][y] = satPositions.FindIndex(x => x.Checksum == satelliteKey);
                            selectedLnbListItems[x][y] = lnbTypes.FindIndex(x => x.Id == lnbKey);
                            selectedDishListItems[x][y] = dishTypes.FindIndex(x => x.Id == dishKey);
                            if (selectedSatListItems[x][y] == -1)
                                selectedSatListItems[x][y] = 0;
                            if (selectedLnbListItems[x][y] == -1)
	                            selectedLnbListItems[x][y] = 0;
                            if (selectedDishListItems[x][y] == -1)
	                            selectedDishListItems[x][y] = 0;
                        }
                    }
                }
            }
        }


        private int[] selectedDiseqcOptions;
        private int[][] selectedSatListItems;
        private int[][] selectedLnbListItems;
        private int[][] selectedDishListItems;
        public List<TunerMetadata> Tuners { get; }

        private string TableGuid;
        private string TableGuid2;
        private bool HasChanges;

        private void Save()
        {
            for (int x = 0; x < Tuners.Count; x++)
            {
                if (Tuners[x].Type == STD_TYPE.STD_DVBS)
                {
                    Tuners[x].DiseqcType = selectedDiseqcOptions[x];
                    for (int y = 0; y < 4; y++)
                    {
                        Tuners[x].Satellites[y] = satPositions[selectedSatListItems[x][y]].Checksum;
                        Tuners[x].Lnbs[y] = lnbTypes[selectedLnbListItems[x][y]].Id;
                        Tuners[x].Dishes[y] = dishTypes[selectedDishListItems[x][y]].Id;
                    }
                }

                if (_scraperStroage.UiTunerTestFor(Tuners[x]))
                {
                    _scraperStroage.UiTunerUpdate(Tuners[x]);
                }
                else
                {
                    _scraperStroage.UiTunerInsert(Tuners[x]);
                }
            }
            HasChanges = false;
        }

        public void Render()
        {
            bool pOpen = true;
            ImGuiWindowFlags windowFlags = ImGuiWindowFlags.AlwaysAutoResize;
            if (HasChanges)
                windowFlags |= ImGuiWindowFlags.UnsavedDocument;
            ImGui.Begin("Configure Tuners", ref pOpen, windowFlags);

            ImGui.BeginTable(TableGuid, 3, ImGuiTableFlags.Borders);
            for (int x = 0; x < Tuners.Count; x++)
            {
                ImGui.TableNextRow();
                ImGui.TableSetColumnIndex(0);
                ImGui.Text(Tuners[x].Name);
                ImGui.TableSetColumnIndex(1);
                ImGui.Text(Tuners[x].Type.ToString());
                ImGui.TableSetColumnIndex(2);

                if (Tuners[x].Type == STD_TYPE.STD_DVBS)
                {
                    ImGui.PushID(String.Format("{0}_single", x));
                    if (ImGui.RadioButton("Single LNB", ref selectedDiseqcOptions[x], 0))
                    {
                        HasChanges = true;
                    }
                    ImGui.PopID();
                    ImGui.SameLine();

                    ImGui.PushID(String.Format("{0}_tone", x));
                    if (ImGui.RadioButton("Tone Burst", ref selectedDiseqcOptions[x], 1))
                    {
                        HasChanges = true;
                    }
                    ImGui.PopID();
                    ImGui.SameLine();

                    ImGui.PushID(String.Format("{0}_diseqcSwitch", x));
                    if (ImGui.RadioButton("DiSEqC 1.0", ref selectedDiseqcOptions[x], 2))
                    {
                        HasChanges = true;
                    }
                    ImGui.PopID();

                    int numSats = 0;
                    switch (selectedDiseqcOptions[x])
                    {
                        case 0: numSats = 1; break;
                        case 1: numSats = 2; break;
                        case 2: numSats = 4; break;
                        default: throw new NotImplementedException(String.Format("{0} {1}", nameof(TunerMetadata.DiseqcType), selectedDiseqcOptions[x]));
                    }

                    for (int y = 0; y < numSats; y++)
                    {
                        ImGui.PushID(String.Format("{0}_combo{1}sat", x, y));
                        if (ImGui.BeginCombo(String.Format("Port {0}", y + 1), satPositions[selectedSatListItems[x][y]].ToString()))
                        {
                            for (int z = 0; z < satPositions.Count; z++)
                            {
                                bool isSelected = selectedSatListItems[x][y] == z;
                                if (ImGui.Selectable(satPositions[z].ToString(), isSelected))
                                {
                                    selectedSatListItems[x][y] = z;
                                    HasChanges = true;
                                }
                            }
                            ImGui.EndCombo();
                        }
                        ImGui.PopID();

                        ImGui.PushID(String.Format("{0}_combo{1}lnb", x, y));
                        if (ImGui.BeginCombo(String.Format("LNB {0}",y + 1), lnbTypes[selectedLnbListItems[x][y]].ToString()))
                        {
	                        for (int z = 0; z < lnbTypes.Count; z++)
	                        {
		                        bool isSelected = selectedLnbListItems[x][y] == z;
		                        if (ImGui.Selectable(lnbTypes[z].ToString(), isSelected))
		                        {
			                        selectedLnbListItems[x][y] = z;
			                        HasChanges = true;
		                        }
	                        }
                            ImGui.EndCombo();
                        }
                        ImGui.PopID();

                        ImGui.PushID(String.Format("{0}_combo{1}dish", x, y));
                        if (ImGui.BeginCombo(String.Format("Dish {0}", y + 1), dishTypes[selectedDishListItems[x][y]].ToString()))
                        {
	                        for (int z = 0; z < dishTypes.Count; z++)
	                        {
		                        bool isSelected = selectedDishListItems[x][y] == z;
		                        if (ImGui.Selectable(dishTypes[z].ToString(), isSelected))
		                        {
			                        selectedDishListItems[x][y] = z;
			                        HasChanges = true;
		                        }
	                        }
	                        ImGui.EndCombo();
                        }
                        ImGui.PopID();
					}
                }
            }
            ImGui.EndTable();

            ImGui.Separator();
            ImGui.BeginTable(TableGuid2, 7);
            ImGui.TableNextRow();
            ImGui.TableSetColumnIndex(3);
            if (ImGui.Button("OK"))
            {
                if (HasChanges)
                    Save();
                Closed = true;
            }
            ImGui.TableSetColumnIndex(4);
            if (ImGui.Button("Cancel"))
            {
                Closed = true;
            }
            ImGui.TableSetColumnIndex(5);
            ImGui.BeginDisabled(!HasChanges);
            if (ImGui.Button("Apply"))
            {
                Save();
            }
            ImGui.EndDisabled();
            ImGui.EndTable();

            ImGui.End();
            if (!pOpen)
            {
                Closed = true;
            }
        }
        
        public bool Closed { get; set; }

    }
}
