import sys
import app
import ui
import math
import time

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

GLHelper = FindModuleByAttributes(['GetTime', 'AppendChat'], 'GLHelper')
GLPlayer = FindModuleByAttributes(['GetName', 'IsOnline', 'IsReady'], 'GLPlayer')
GLPythonPlayer = FindModuleByAttributes(['GetTargetVNUM', 'GetItemNameByVNUM', 'GetItemSlotByVnum', 'GetVIDByVNUM'], 'GLPythonPlayer')
GLPythonNetworkStream = FindModuleByAttributes(['SendRefinePacket'], 'GLPythonNetworkStream')
net = FindModuleByAttributes(['SendGiveItemPacket'], 'm2netm2g')
GLItem = FindModuleByAttributes(['GetItemType', 'SelectItem'], 'item')

def Log(msg):
    try: GLHelper.AppendChat(7, "|cffff6060[Auto-Upgrade] - |ccc00ff00" + str(msg))
    except: pass

class OtoItemUpgrade(ui.BoardWithTitleBar):
    def __init__(self):
        ui.BoardWithTitleBar.__init__(self)
        self.AddFlag("movable")
        self.AddFlag("float")
        self.SetPosition(150, 100)
        self.SetSize(340, 350)
        self.SetTitleName("Auto Item Upgrade - Powered by GLBot++")
        self.SetCloseEvent(self.Close)

        self.UpgradeList = []
        self.UpgradeState = False
        self.UpgradeTick = 0
        self.Index = 0
        self.BlacksmithVNUM = 20045
        self.TargetPlus = 9

        self.DemirciTitle = ui.TextLine()
        self.DemirciTitle.SetParent(self)
        self.DemirciTitle.SetPosition(20, 35)
        self.DemirciTitle.SetText("Blacksmith Settings")
        self.DemirciTitle.SetPackedFontColor(0xfffcc419)
        self.DemirciTitle.Show()

        self.DemirciSlot = ui.SlotBar()
        self.DemirciSlot.SetParent(self)
        self.DemirciSlot.SetPosition(20, 55)
        self.DemirciSlot.SetSize(65, 18)
        self.DemirciSlot.Show()

        self.DemirciEdit = ui.EditLine()
        self.DemirciEdit.SetParent(self.DemirciSlot)
        self.DemirciEdit.SetPosition(4, 2)
        self.DemirciEdit.SetSize(57, 18)
        self.DemirciEdit.SetMax(6)
        self.DemirciEdit.SetNumberMode()
        self.DemirciEdit.SetText("20045")
        self.DemirciEdit.Show()

        self.BtnHedefAl = ui.Button()
        self.BtnHedefAl.SetParent(self)
        self.BtnHedefAl.SetPosition(95, 53)
        self.BtnHedefAl.SetUpVisual("d:/ymir work/ui/public/large_Button_01.sub")
        self.BtnHedefAl.SetOverVisual("d:/ymir work/ui/public/large_Button_02.sub")
        self.BtnHedefAl.SetDownVisual("d:/ymir work/ui/public/large_Button_03.sub")
        self.BtnHedefAl.SetText("Get From Target")
        self.BtnHedefAl.SetEvent(self.HedeftenDemirciAl)
        self.BtnHedefAl.Show()

        self.PlusTitle = ui.TextLine()
        self.PlusTitle.SetParent(self)
        self.PlusTitle.SetPosition(245, 35)
        self.PlusTitle.SetText("Target +")
        self.PlusTitle.SetPackedFontColor(0xfffcc419)
        self.PlusTitle.Show()

        self.PlusSlot = ui.SlotBar()
        self.PlusSlot.SetParent(self)
        self.PlusSlot.SetPosition(245, 55)
        self.PlusSlot.SetSize(35, 18)
        self.PlusSlot.Show()

        self.PlusEdit = ui.EditLine()
        self.PlusEdit.SetParent(self.PlusSlot)
        self.PlusEdit.SetPosition(4, 2)
        self.PlusEdit.SetSize(27, 18)
        self.PlusEdit.SetMax(1)
        self.PlusEdit.SetNumberMode()
        self.PlusEdit.SetText("9")
        self.PlusEdit.Show()

        self.ItemTitle = ui.TextLine()
        self.ItemTitle.SetParent(self)
        self.ItemTitle.SetPosition(20, 85)
        self.ItemTitle.SetText("Add Item VNUM")
        self.ItemTitle.SetPackedFontColor(0xfffcc419)
        self.ItemTitle.Show()

        self.ItemSlot = ui.SlotBar()
        self.ItemSlot.SetParent(self)
        self.ItemSlot.SetPosition(20, 105)
        self.ItemSlot.SetSize(65, 18)
        self.ItemSlot.Show()

        self.ItemEdit = ui.EditLine()
        self.ItemEdit.SetParent(self.ItemSlot)
        self.ItemEdit.SetPosition(4, 2)
        self.ItemEdit.SetSize(57, 18)
        self.ItemEdit.SetMax(6)
        self.ItemEdit.SetNumberMode()
        self.ItemEdit.SetText("")
        self.ItemEdit.Show()

        self.BtnEkle = ui.Button()
        self.BtnEkle.SetParent(self)
        self.BtnEkle.SetPosition(95, 103)
        self.BtnEkle.SetUpVisual("d:/ymir work/ui/public/large_Button_01.sub")
        self.BtnEkle.SetOverVisual("d:/ymir work/ui/public/large_Button_02.sub")
        self.BtnEkle.SetDownVisual("d:/ymir work/ui/public/large_Button_03.sub")
        self.BtnEkle.SetText("Add to List")
        self.BtnEkle.SetEvent(self.ItemEkle)
        self.BtnEkle.Show()

        self.BtnTemizle = ui.Button()
        self.BtnTemizle.SetParent(self)
        self.BtnTemizle.SetPosition(245, 103)
        self.BtnTemizle.SetUpVisual("d:/ymir work/ui/public/middle_Button_01.sub")
        self.BtnTemizle.SetOverVisual("d:/ymir work/ui/public/middle_Button_02.sub")
        self.BtnTemizle.SetDownVisual("d:/ymir work/ui/public/middle_Button_03.sub")
        self.BtnTemizle.SetText("Clear")
        self.BtnTemizle.SetEvent(self.ListeTemizle)
        self.BtnTemizle.Show()

        self.BtnEnvanterTara = ui.Button()
        self.BtnEnvanterTara.SetParent(self)
        self.BtnEnvanterTara.SetPosition(20, 130)
        self.BtnEnvanterTara.SetUpVisual("d:/ymir work/ui/public/XLarge_Button_01.sub")
        self.BtnEnvanterTara.SetOverVisual("d:/ymir work/ui/public/XLarge_Button_02.sub")
        self.BtnEnvanterTara.SetDownVisual("d:/ymir work/ui/public/XLarge_Button_03.sub")
        self.BtnEnvanterTara.SetText("Refresh Inventory (Weapons/Armors)")
        self.BtnEnvanterTara.SetEvent(self.EnvanterGerecleriTara)
        self.BtnEnvanterTara.Show()

        self.ListBar = ui.Bar()
        self.ListBar.SetParent(self)
        self.ListBar.SetPosition(20, 165)
        self.ListBar.SetSize(300, 100)
        self.ListBar.SetColor(0xaa000000)
        self.ListBar.Show()

        self.ListBox = ui.ListBoxEx()
        self.ListBox.SetParent(self.ListBar)
        self.ListBox.SetPosition(5, 5)
        self.ListBox.SetSize(290, 90)
        self.ListBox.SetViewItemCount(4)
        self.ListBox.Show()

        self.ListScroll = ui.ScrollBar()
        self.ListScroll.SetParent(self.ListBar)
        self.ListScroll.SetPosition(285, 5)
        self.ListScroll.SetScrollBarSize(90)
        self.ListScroll.Show()
        self.ListBox.SetScrollBar(self.ListScroll)

        self.StatusText = ui.TextLine()
        self.StatusText.SetParent(self)
        self.StatusText.SetPosition(20, 275)
        self.StatusText.SetText("Status: Ready")
        self.StatusText.Show()

        self.BtnBaslat = ui.Button()
        self.BtnBaslat.SetParent(self)
        self.BtnBaslat.SetPosition(20, 305)
        self.BtnBaslat.SetUpVisual("d:/ymir work/ui/public/large_Button_01.sub")
        self.BtnBaslat.SetOverVisual("d:/ymir work/ui/public/large_Button_02.sub")
        self.BtnBaslat.SetDownVisual("d:/ymir work/ui/public/large_Button_03.sub")
        self.BtnBaslat.SetText("Start")
        self.BtnBaslat.SetEvent(self.ToggleUpgrade)
        self.BtnBaslat.Show()

        self.BtnSil = ui.Button()
        self.BtnSil.SetParent(self)
        self.BtnSil.SetPosition(230, 305)
        self.BtnSil.SetUpVisual("d:/ymir work/ui/public/large_Button_01.sub")
        self.BtnSil.SetOverVisual("d:/ymir work/ui/public/large_Button_02.sub")
        self.BtnSil.SetDownVisual("d:/ymir work/ui/public/large_Button_03.sub")
        self.BtnSil.SetText("Delete Selected")
        self.BtnSil.SetEvent(self.SeciliSil)
        self.BtnSil.Show()

        # --- ARTIK DEFAULT OLARAK LISTEYI OTOMATIK CEKIYOR ---
        self.EnvanterGerecleriTara()
        # -----------------------------------------------------

        self.Show()

    def Close(self):
        self.UpgradeState = False
        self.Hide()

    def HedeftenDemirciAl(self):
        try:
            if not GLPythonPlayer: return
            vnum = GLPythonPlayer.GetTargetVNUM()
            if vnum > 0:
                self.DemirciEdit.SetText(str(vnum))
                Log("Blacksmith VNUM acquired: " + str(vnum))
            else:
                Log("ERROR: Please target a blacksmith/NPC first!")
        except:
            Log("ERROR: Failed to acquire target!")

    def EnvanterGerecleriTara(self):
        if not GLItem or not GLPythonPlayer:
            return

        player_mod = FindModuleByAttributes(['GetItemIndex', 'INVENTORY_PAGE_SIZE'])
        page_size = getattr(player_mod, 'INVENTORY_PAGE_SIZE', 45) if player_mod else 45
        total_slots = page_size * 4

        bulunan_sayac = 0

        for slot in range(total_slots):
            try:
                vnum = player_mod.GetItemIndex(slot) if player_mod else 0
                if vnum <= 0:
                    continue

                GLItem.SelectItem(vnum)
                item_type = GLItem.GetItemType()

                if item_type == 0 or item_type == 1:
                    if any(v == vnum for v, n in self.UpgradeList):
                        continue

                    name = GLPythonPlayer.GetItemNameByVNUM(vnum) if GLPythonPlayer else "Item-" + str(vnum)
                    self.UpgradeList.append((vnum, name))
                    bulunan_sayac += 1
            except:
                continue

        if bulunan_sayac > 0:
            self.ListeYenile()
            Log("Auto-Load: Found and listed %d Weapons/Armors." % bulunan_sayac)

    def ItemEkle(self):
        try:
            vnum = int(self.ItemEdit.GetText())
        except:
            Log("ERROR: Invalid VNUM!")
            return
        if vnum <= 0:
            Log("ERROR: Invalid VNUM!")
            return
        for v, n in self.UpgradeList:
            if v == vnum:
                Log("This item is already in the list!")
                return
        try:
            name = GLPythonPlayer.GetItemNameByVNUM(vnum) if GLPythonPlayer else "Item-" + str(vnum)
        except:
            name = "Item-" + str(vnum)
        self.UpgradeList.append((vnum, name))
        self.ListeYenile()
        self.ItemEdit.SetText("")
        Log("Added: " + name + " (" + str(vnum) + ")")

    def ListeTemizle(self):
        self.UpgradeList = []
        self.ListeYenile()
        Log("List cleared.")

    def SeciliSil(self):
        idx = self.ListBox.GetSelectedItem()
        if idx is not None and idx >= 0 and idx < len(self.UpgradeList):
            silinen = self.UpgradeList[idx]
            del self.UpgradeList[idx]
            self.ListeYenile()
            Log("Removed: " + silinen[1])
        else:
            Log("Click on an item from the list to remove it.")

    def ListeYenile(self):
        self.ListBox.RemoveAllItems()
        for i, (vnum, name) in enumerate(self.UpgradeList):
            txt = ui.TextLine()
            txt.SetText(str(i+1) + ". " + name + " (" + str(vnum) + ")")
            self.ListBox.AppendItem(txt)

    def ToggleUpgrade(self):
        if self.UpgradeState:
            self.UpgradeState = False
            self.BtnBaslat.SetText("Start")
            self.StatusText.SetText("Status: Stopped")
            Log("Upgrade process stopped.")
        else:
            if len(self.UpgradeList) == 0:
                Log("ERROR: List is empty!")
                return
            try: self.BlacksmithVNUM = int(self.DemirciEdit.GetText())
            except: self.BlacksmithVNUM = 20045
            try: self.TargetPlus = int(self.PlusEdit.GetText())
            except: self.TargetPlus = 9
            if self.TargetPlus < 1 or self.TargetPlus > 9:
                self.TargetPlus = 9
            self.Index = 0
            self.UpgradeState = True
            self.UpgradeTick = GLHelper.GetTime() if GLHelper else 0
            self.BtnBaslat.SetText("Stop")
            self.StatusText.SetText("Status: Running...")
            Log("Upgrade started! Target: +" + str(self.TargetPlus) + " | " + str(len(self.UpgradeList)) + " items")

    def OnUpdate(self):
        if not self.UpgradeState:
            return
        if not GLPlayer or not GLHelper or not GLPythonPlayer or not net or not GLPythonNetworkStream:
            return
        if not GLPlayer.IsReady() or not GLPlayer.IsOnline():
            return
        if GLHelper.GetTime() - self.UpgradeTick < 250:
            return
        self.UpgradeTick = GLHelper.GetTime()

        if self.Index >= len(self.UpgradeList):
            Log("All items processed! Finished.")
            self.UpgradeState = False
            self.BtnBaslat.SetText("Start")
            self.StatusText.SetText("Status: Completed!")
            return

        entered_vnum = self.UpgradeList[self.Index][0]
        name = self.UpgradeList[self.Index][1]
        base_vnum = entered_vnum - (entered_vnum % 10)

        iSlot = -1
        current_plus = -1
        for plus in range(self.TargetPlus):
            check_vnum = base_vnum + plus
            slot = GLPythonPlayer.GetItemSlotByVnum(check_vnum)
            if slot != -1:
                iSlot = slot
                current_plus = plus
                break

        if iSlot == -1:
            target_vnum = base_vnum + self.TargetPlus
            target_slot = GLPythonPlayer.GetItemSlotByVnum(target_vnum)
            if target_slot != -1:
                Log(name + " reached +%d! Done." % self.TargetPlus)
            else:
                Log(name + " not found in inventory (might be broken), skipping...")
            self.Index += 1
            return

        BLACKSMITH_VID = GLPythonPlayer.GetVIDByVNUM(self.BlacksmithVNUM)
        if BLACKSMITH_VID == 0:
            Log("ERROR: Blacksmith not found! VNUM: " + str(self.BlacksmithVNUM))
            self.UpgradeState = False
            self.BtnBaslat.SetText("Start")
            self.StatusText.SetText("ERROR: No Blacksmith!")
            return

        self.StatusText.SetText(name + " +%d -> +%d (%d/%d)" % (current_plus, self.TargetPlus, self.Index+1, len(self.UpgradeList)))

        try:
            net.SendGiveItemPacket(BLACKSMITH_VID, iSlot, 1)
            GLPythonNetworkStream.SendRefinePacket(iSlot, 1)
        except Exception as e:
            Log("Upgrade error: " + str(e))

try: otoUpgrade.Close()
except: pass
otoUpgrade = OtoItemUpgrade()
