@inject IJSRuntime JsRuntime;
@using Services.Website
@implements IDisposable
@inject IKeyService KeyService
@inject IBuildOrderService BuildOrderService
@inject IImmortalSelectionService FilterService

@inject IEconomyService EconomyService
@inject ITimingService TimingService
@inject IToastService ToastService
@inject IDataCollectionService DataCollectionService


<InputPanelComponent>
    <div class="keyContainer">
        @foreach (var hotkey in hotkeys)
        {
            if (hotkey.IsHidden)
            {
                continue;
            }


            var color = (hotkey.KeyText.Equals("SPACE") && KeyService.IsHoldingSpace()) || KeyService.GetAllPressedKeys().Contains(hotkey.KeyText)
                ? hotkey.GetColor()
                : hotkey.GetColor();

            var x = hotkey.PositionX * Size;
            var y = hotkey.PositionY * Size + (hotkey.PositionY == 0 ? 5 : -50);

            var width = Size * hotkey.Width;
            var height = hotkey.PositionY == 0 ? 50 : Size;

            var borderRadius = hotkey.PositionY == 0 ? 12 : 0;

            var border = "1px solid black";
            if (hotkey.KeyText.Equals(key))
            {
                border = "5px solid black";
            }

            if (hotkey.KeyText.Equals(controlGroup))
            {
                color = "#257525";
            }

            if (hotkey.KeyText.Equals("SPACE") && KeyService.IsHoldingSpace())
            {
                border = "5px solid green";
            }

            var keyText = hotkey.KeyText.Equals("CAPSLOCK") ? "Caps"
                : hotkey.KeyText.Equals("CONTROL") ? "Ctrl"
                : hotkey.KeyText.Equals("SHIFT") ? "Shift"
                : hotkey.KeyText.Equals("X") ? "X"
                : hotkey.KeyText.Equals("SPACE") ? "Space" : hotkey.KeyText;


            var controlStyle = $"background-color:{color}; " +
                               $"width: {width}px; " +
                               "border-top: 1px solid black; " +
                               "border-left: 1px solid black; " +
                               "border-right: 1px solid black; " +
                               $"border-top-left-radius: {borderRadius}px; " +
                               $"border-top-right-radius: {borderRadius}px; " +
                               "overflow: hidden; " +
                               "text-align: center;";

            var keyStyle = $"background-color:{color}; " +
                           $"border: {border}; " +
                           $"width: {width}px; " +
                           $"height: {height}px;  " +
                           "overflow: hidden; " +
                           "padding: 4px;";

            var usedStyle = hotkey.PositionY == 0 ? controlStyle : keyStyle;

            <div style="position:relative;
                cursor:pointer;
                top:@y.ToString()px;
            left:@x.ToString()px;
            width: 0px;
            height: 0px;">

                <div @onclick="e => ButtonClicked(e, hotkey)" style="@usedStyle">
                    @keyText
                    @foreach (var entity in data.Values)
                    {
                        if (InvalidKey(entity, hotkey) || InvalidKeyGroup(entity, hotkey) || InvalidHoldSpace(entity))
                        {
                            continue;
                        }

                        if (InvalidFaction(entity))
                        {
                            continue;
                        }

                        if (InvalidVanguard(entity) || InvalidNonVanguard(entity))
                        {
                            continue;
                        }

                        var isVanguard = entity.VanguardAdded() != null;
                        var style = isVanguard ? "font-weight: bold;" : "";

                        if (BuildOrderService.WillMeetRequirements(entity) == null)
                        {
                            style += "color:gray; font-style: italic;";
                        }


                        <div style="@style">@entity.Info()?.Name</div>
                    }
                </div>
            </div>
        }
    </div>
</InputPanelComponent>

<style>
    .keyContainer {
        width: 400px;
        max-width: 95vw;
        height: 350px;
        outline: 3px solid black;
        border-radius: 8px;
        background-color: #282A30;
        margin: auto;
    }

    @@media only screen and (max-width: 1025px) {
        .keyContainer {
            transform: scale(0.85) translateX(-20px);
            background-color: transparent;
            outline: none;
        }
    }
</style>

@code {

    [Parameter] public int Size { get; set; } = 100;

    readonly Dictionary<string, EntityModel> data = EntityModel.GetDictionary();
    readonly List<HotkeyModel> hotkeys = HotkeyModel.GetAll();

    private string controlGroup = "C";
    private string key = "";

    protected override void OnInitialized()
    {
        base.OnInitialized();

        KeyService.Subscribe(OnKeyPressed);
        FilterService.Subscribe(StateHasChanged);
        BuildOrderService.Subscribe(OnBuilderOrderChanged);
    }

    void IDisposable.Dispose()
    {
        KeyService.Unsubscribe(OnKeyPressed);
        FilterService.Unsubscribe(StateHasChanged);
        BuildOrderService.Unsubscribe(OnBuilderOrderChanged);
    }

    int completedTimeCount;

    void OnBuilderOrderChanged()
    {
        if (BuildOrderService.UniqueCompletedTimes.Count != completedTimeCount)
        {
            completedTimeCount = BuildOrderService.UniqueCompletedTimes.Count;
            StateHasChanged();
        }
    }

    protected override bool ShouldRender()
    {
#if DEBUG
        JsRuntime.InvokeVoidAsync("console.time", "HotKeyViewerComponent");
#endif

        return true;
    }

    protected override void OnAfterRender(bool firstRender)
    {
#if DEBUG
        JsRuntime.InvokeVoidAsync("console.timeEnd", "HotKeyViewerComponent");
#endif
    }

    // Move to Filter Service
    bool InvalidFaction(EntityModel entity)
    {
        if (entity.Faction() != null && entity.Faction()?.Faction != FilterService.GetFaction() && FilterService.GetFaction() != DataType.Any)
        {
            return true;
        }

        return false;
    }

    // Move to Filter Service
    bool InvalidVanguard(EntityModel entity)
    {
        if (entity.VanguardAdded() != null
            && entity.VanguardAdded()?.ImmortalId != FilterService.GetImmortal()
            && FilterService.GetImmortal() != DataType.Any)
        {
            return true;
        }

        return false;
    }

    // Move to Filter Service
    bool InvalidNonVanguard(EntityModel entity)
    {
        if (entity.Replaceds().Count > 0)
        {
            foreach (var replaced in entity.Replaceds())
            {
                if (FilterService.GetImmortal() == replaced.ImmortalId)
                {
                    return true;
                }
            }
        }

        return false;
    }

    bool InvalidKey(EntityModel entity, HotkeyModel key)
    {
        if (entity.Hotkey()?.Hotkey == key.KeyText)
        {
            return false;
        }

        return true;
    }

    bool InvalidKeyGroup(EntityModel entity, HotkeyModel key)
    {
        if (entity.Hotkey()?.HotkeyGroup == controlGroup)
        {
            return false;
        }

        return true;
    }

    bool InvalidKey(EntityModel entity)
    {
        if (entity.Hotkey()?.Hotkey == key)
        {
            return false;
        }

        return true;
    }

    bool InvalidKeyGroup(EntityModel entity)
    {
        if (entity.Hotkey()?.HotkeyGroup == controlGroup)
        {
            return false;
        }

        return true;
    }

    bool InvalidHoldSpace(EntityModel entity)
    {
        if (entity.Hotkey()?.HoldSpace == KeyService.IsHoldingSpace())
        {
            return false;
        }

        return true;
    }

    void OnKeyPressed()
    {
        var controlGroupWas = controlGroup;
        var keyWas = key;

        if (KeyService.GetAllPressedKeys().Contains("Z"))
        {
            controlGroup = "Z";
        }

        if (KeyService.GetAllPressedKeys().Contains("X"))
        {
            controlGroup = "X";
        }

        if (KeyService.GetAllPressedKeys().Contains("C"))
        {
            controlGroup = "C";
        }

        if (KeyService.GetAllPressedKeys().Contains("D"))
        {
            controlGroup = "D";
        }

        if (KeyService.GetAllPressedKeys().Contains("V"))
        {
            controlGroup = "V";
        }

        if (KeyService.GetAllPressedKeys().Contains("ALT"))
        {
            controlGroup = "ALT";
        }

        if (KeyService.GetAllPressedKeys().Contains("SHIFT"))
        {
            controlGroup = "SHIFT";
        }

        if (KeyService.GetAllPressedKeys().Contains("CONTROL"))
        {
            controlGroup = "CONTROL";
        }

        if (KeyService.GetAllPressedKeys().Count > 0)
        {
            key = KeyService.GetAllPressedKeys().First();
        }

        if (controlGroupWas != controlGroup || keyWas != key)
        {
            StateHasChanged();
        }
    }


    private void HandleClick()
    {
        var hotkey = KeyService.GetHotkey();

        if (hotkey is "`")
            HandleCancelEntity();

        if (EntityFromKey(hotkey, out var entity))
            return;

        if (BuildOrderService.Add(entity!, EconomyService))
            EconomyService.Calculate(BuildOrderService, TimingService, BuildOrderService.GetLastRequestInterval());
    }

    private void HandleCancelEntity()
    {
        BuildOrderService.RemoveLast();
        EconomyService.Calculate(BuildOrderService, TimingService, BuildOrderService.GetLastRequestInterval());
    }

    private bool EntityFromKey(string? hotkey, out EntityModel? entity)
    {
        var hotkeyGroup = KeyService.GetHotkeyGroup();
        var isHoldSpace = KeyService.IsHoldingSpace();
        var faction = FilterService.GetFaction();
        var immortal = FilterService.GetImmortal();

        entity = EntityModel.GetFrom(hotkey!, hotkeyGroup, isHoldSpace, faction, immortal);

        return entity == null;
    }

    private void ButtonClicked(MouseEventArgs mouseEventArgs, HotkeyModel hotkey)
    {
        DataCollectionService.SendEvent(
            DataCollectionKeys.BuildCalcInput,
            new Dictionary<string, string> { { "key", hotkey.KeyText.ToLower() }, { "input-source", "mouse" } }
        );


        if (hotkey.KeyText.Equals(HotKeyType.SPACE.ToString()))
        {
            if (KeyService.IsHoldingSpace())
            {
                KeyService.RemovePressedKey(hotkey.KeyText);
            }
            else
            {
                KeyService.AddPressedKey(hotkey.KeyText);
            }
        }
        else
        {
            KeyService.AddPressedKey(hotkey.KeyText);
            KeyService.RemovePressedKey(hotkey.KeyText);
        }
    }

}