import ui
import chr
import dbg
import app
import background
import math
import time
import sys

def FindModuleByAttributes(attributes, fallback_name=None):
    for mod_name, mod in sys.modules.items():
        if mod is None:
            continue
        if all(hasattr(mod, attr) for attr in attributes):
            return mod
    if fallback_name:
        try: return __import__(fallback_name)
        except: pass
    return None

# Dynamic Module Binder
GLHelper              = FindModuleByAttributes(['GetTime', 'AppendChat'], 'GLHelper')
GLList                = FindModuleByAttributes(['GetObjectList'], 'GLList')
GLPlayer              = FindModuleByAttributes(['GetName', 'IsOnline', 'IsReady'], 'GLPlayer')
GLPythonPlayer        = FindModuleByAttributes(['GetTargetVNUM', 'GetItemNameByVNUM', 'GetItemSlotByVnum'], 'GLPythonPlayer')
GLPythonNetworkStream = FindModuleByAttributes(['SendItemUsePacket'], 'GLPythonNetworkStream')
player                = FindModuleByAttributes(['GetItemIndex', 'SendDragonSoulRefine'], 'playerm2g2')

def Log(msg):
    if GLHelper:
        GLHelper.AppendChat(7, "|cffff6060[Alchemy Bot] - |ccc00ff00" + str(msg))

def GetBestCombination():
    if not player:
        return 0, 0

    SIMYA = []
    SIMYA2 = []

    ONIKS = 1
    for slot in range(960,992):
        ID = player.GetItemIndex(10,slot)
        if ID == 0:
            ONIKS = 0
            break

    GRENA = 1
    for slot in range(768,800):
        ID = player.GetItemIndex(10,slot)
        if ID == 0:
            GRENA = 0
            break

    SAFIR = 1
    for slot in range(576,608):
        ID = player.GetItemIndex(10,slot)
        if ID == 0:
            SAFIR = 0
            break

    YESIM = 1
    for slot in range(384,416):
        ID = player.GetItemIndex(10,slot)
        if ID == 0:
            YESIM = 0
            break

    YAKUT = 1
    for slot in range(192,224):
        ID = player.GetItemIndex(10,slot)
        if ID == 0:
            YAKUT = 0
            break

    ELMAS = 1
    for slot in range(32):
        ID = player.GetItemIndex(10,slot)
        if ID == 0:
            ELMAS = 0
            break

    if ONIKS == 1:
        SIMYA.extend([960, 961])
        SIMYA2.extend([160000, 160000])
    elif GRENA == 1:
        SIMYA.extend([768, 769])
        SIMYA2.extend([150000, 150000])
    elif SAFIR == 1:
        SIMYA.extend([576, 577])
        SIMYA2.extend([140000, 140000])
    elif YESIM == 1:
        SIMYA.extend([384, 385])
        SIMYA2.extend([130000, 130000])
    elif YAKUT == 1:
        SIMYA.extend([192, 193])
        SIMYA2.extend([120000, 120000])
    elif ELMAS == 1:
        SIMYA.extend([0, 1])
        SIMYA2.extend([110000, 110000])

    # Scan inventory slots
    for slot in range(32):
        ID = player.GetItemIndex(10,slot)
        if ID != 0:
            SIMYA.append(slot)
            SIMYA2.append(ID)

    for slot in range(192,224):
        ID = player.GetItemIndex(10,slot)
        if ID != 0:
            SIMYA.append(slot)
            SIMYA2.append(ID)

    for slot in range(384,416):
        ID = player.GetItemIndex(10,slot)
        if ID != 0:
            SIMYA.append(slot)
            SIMYA2.append(ID)

    for slot in range(576,608):
        ID = player.GetItemIndex(10,slot)
        if ID != 0:
            SIMYA.append(slot)
            SIMYA2.append(ID)

    for slot in range(768,800):
        ID = player.GetItemIndex(10,slot)
        if ID != 0:
            SIMYA.append(slot)
            SIMYA2.append(ID)

    for slot in range(960,992):
        ID = player.GetItemIndex(10,slot)
        if ID != 0:
            SIMYA.append(slot)
            SIMYA2.append(ID)

    for slot in range(96):
        ID = player.GetItemIndex(10,slot)
        if ID != 0:
            SIMYA.append(slot)
            SIMYA2.append(ID)

    for slot in range(192,288):
        ID = player.GetItemIndex(10,slot)
        if ID != 0:
            SIMYA.append(slot)
            SIMYA2.append(ID)

    for slot in range(384,480):
        ID = player.GetItemIndex(10,slot)
        if ID != 0:
            SIMYA.append(slot)
            SIMYA2.append(ID)

    for slot in range(576,672):
        ID = player.GetItemIndex(10,slot)
        if ID != 0:
            SIMYA.append(slot)
            SIMYA2.append(ID)

    for slot in range(768,864):
        ID = player.GetItemIndex(10,slot)
        if ID != 0:
            SIMYA.append(slot)
            SIMYA2.append(ID)

    for slot in range(960,1056):
        ID = player.GetItemIndex(10,slot)
        if ID != 0:
            SIMYA.append(slot)
            SIMYA2.append(ID)

    # Match combinations
    for birlestir in range(len(SIMYA)):
        for birlestir2 in range(len(SIMYA)):
            if birlestir > birlestir2:
                continue
            elif int(SIMYA2[birlestir]) != int(SIMYA2[birlestir2]):
                continue
            elif int(SIMYA[birlestir]) == int(SIMYA[birlestir2]):
                continue
            else:
                return SIMYA[birlestir] , SIMYA[birlestir2]
    return 0 , 0

class RefineBotUI(ui.BoardWithTitleBar):
    def __init__(self):
        ui.BoardWithTitleBar.__init__(self)
        self.AddFlag("movable")
        self.AddFlag("float")
        self.SetPosition(200, 150)
        self.SetSize(260, 160)
        self.SetTitleName("Alchemy Bot - Powered by GLBot++")
        self.UI = UI()

        self.corLabel = self.UI.Label(self, 15, 40, "Count to Open :")
        self.corsayis = self.UI.EditLine(self, "1", 170, 40, 65, 15, 3)

        self.sandivnumlabel = self.UI.Label(self, 15, 70, "Chest VNUM (Cor=50255) :")
        self.sandikvnum = self.UI.EditLine(self, "50255", 170, 70, 65, 15, 10)

        self.OpenCors = self.UI.Button(self, 'Open Chests', '', 25, 110, self.OpenCorsFunction, "large")
        self.RefineStartButton = self.UI.Button(self, 'Refine', '', 140, 110, self.RefineStartButtonFunc, "large")

        self.RefineState = False
        self.OpenCorState = False

        current_time = GLHelper.GetTime() if GLHelper else 0
        self.RefineTick = current_time
        self.CorTick = current_time
        self.cor = 0

        self.Show()

    def OpenCorsFunction(self):
        try:
            self.corsayisi = int(self.corsayis[1].GetText())
            self.sandik = int(self.sandikvnum[1].GetText())
            self.cor = self.corsayisi
            self.OpenCorState = True
            Log("Started opening chests... Target count: " + str(self.cor))
        except:
            Log("Error: Invalid Chest VNUM or Count!")

    def RefineStartButtonFunc(self):
        if not self.RefineState:
            self.RefineState = True
            self.RefineStartButton.SetText("Stop")
            Log("Alchemy refinement process started.")
        else:
            self.RefineState = False
            self.RefineStartButton.SetText("Refine")
            Log("Alchemy refinement process stopped.")

    def OnUpdate(self):
        if not GLPlayer or not GLHelper or not GLPythonPlayer or not GLPythonNetworkStream or not player:
            return

        if not GLPlayer.IsReady() or not GLPlayer.IsOnline():
            return

        current_time = GLHelper.GetTime()

        # Safe Chest Opener Logic (500ms Delay)
        if self.OpenCorState and (current_time - self.CorTick >= 500):
            self.CorTick = current_time
            if self.corsayisi > 0:
                Slot = GLPythonPlayer.GetItemSlotByVnum(self.sandik)
                if Slot >= 0:
                    GLPythonNetworkStream.SendItemUsePacket(Slot)
                    self.corsayisi -= 1
                else:
                    Log("Error: Target chest not found in inventory!")
                    self.OpenCorState = False
            else:
                Log("Process finished! Total opened chests: " + str(self.cor))
                self.OpenCorState = False

        # Safe Refine Logic (750ms Delay)
        if self.RefineState and (current_time - self.RefineTick >= 750):
            self.RefineTick = current_time
            first, second = GetBestCombination()
            if second != 0:
                player.SendDragonSoulRefine(2, {0: (10, int(first), 1), 1: (10, int(second), 1)})
                Log("Upgrading alchemies in slots: [" + str(first) + "] and [" + str(second) + "]")
            else:
                self.RefineStartButton.SetText("Refine")
                self.RefineState = False
                Log("Refinement completed! No more combinations available.")

class UI:
    def Button(self, parent, buttonName, tooltipText, x, y, func, str_type):
        button = ui.Button()
        button.SetParent(parent)
        button.SetPosition(x, y)
        if str_type == "big":
            button.SetUpVisual("d:/ymir work/ui/public/Big_Button_01.sub")
            button.SetOverVisual("d:/ymir work/ui/public/Big_Button_02.sub")
            button.SetDownVisual("d:/ymir work/ui/public/Big_Button_03.sub")
        elif str_type == "large":
            button.SetUpVisual("d:/ymir work/ui/public/large_Button_01.sub")
            button.SetOverVisual("d:/ymir work/ui/public/large_Button_02.sub")
            button.SetDownVisual("d:/ymir work/ui/public/large_Button_03.sub")
        elif str_type == "small":
            button.SetUpVisual("d:/ymir work/ui/public/Small_Button_01.sub")
            button.SetOverVisual("d:/ymir work/ui/public/Small_Button_02.sub")
            button.SetDownVisual("d:/ymir work/ui/public/Small_Button_03.sub")
        button.SetText(buttonName)
        button.SetToolTipText(tooltipText)
        button.Show()
        button.SetEvent(func)
        return button

    def EditLine(self, parent, editlineText, x, y, width, heigh, max_chars):
        SlotBar = ui.SlotBar()
        SlotBar.SetParent(parent)
        SlotBar.SetSize(width, heigh)
        SlotBar.SetPosition(x, y)
        SlotBar.Show()
        Value = ui.EditLine()
        Value.SetParent(SlotBar)
        Value.SetSize(width, heigh)
        Value.SetPosition(5, 1)
        Value.SetMax(max_chars)
        Value.SetText(editlineText)
        Value.Show()
        return SlotBar, Value

    def Label(self, parent, x, y, text):
        Label = ui.TextLine()
        Label.SetParent(parent)
        Label.SetPosition(x, y)
        Label.SetText(text)
        Label.Show()
        return Label

try: refineBot.Close()
except: pass
refineBot = RefineBotUI()
