import asyncio, socket, pickle, threading
from kivy.clock import Clock
from kivy.uix.gridlayout import GridLayout
from kivy.uix.textinput import TextInput
from kivy.uix.button import Button
from kivy.uix.scrollview import ScrollView
from kivy.uix.boxlayout import BoxLayout
from kivymd.app import MDApp
from discord.ext import commands
import discord

class DiscordGUI(BoxLayout):
    def __init__(self, **kwargs):
        super().__init__(orientation='vertical', padding=[10]*4, **kwargs)
        intents = discord.Intents.default()
        intents.typing = intents.presences = False
        self.bot = commands.Bot(command_prefix="!", intents=intents)
        self.channels = []
        self.selected_channel = self.match_channel = None
        self.bot_token_entry = TextInput(hint_text="Bot Token:", multiline=False)
        self.server_id_entry = TextInput(hint_text="Server ID:", multiline=False)
        self.add_widget(self.bot_token_entry)
        self.add_widget(self.server_id_entry)
        self.add_widget(Button(text="Start Discord Bot", on_press=self.run_bot))
        self.fetch_button = Button(text="Fetch Channels", on_press=self.fetch_channels, disabled=True)
        self.add_widget(self.fetch_button)
        self.listen_button = Button(text="Listen", on_press=self.listen_server, disabled=True)
        self.add_widget(self.listen_button)
        self.channel_layout = GridLayout(cols=4, size_hint_y=None)
        self.channel_layout.bind(minimum_height=self.channel_layout.setter('height'))
        self.channel_buttons = ScrollView(size_hint=(1, None), size=(0, 200))
        self.channel_buttons.add_widget(self.channel_layout)
        self.add_widget(self.channel_buttons)

    def run_bot(self, instance):
        loop = asyncio.get_event_loop()
        self.bot_task = loop.create_task(self.bot.start(self.bot_token_entry.text.strip()))
        Clock.schedule_interval(lambda dt: loop.run_until_complete(asyncio.sleep(0)), 0.01)
        self.fetch_button.disabled = False

    def fetch_channels(self, instance):
        asyncio.run(self._fetch_channels())

    async def _fetch_channels(self):
        guild_id = int(self.server_id_entry.text.strip())
        guild = self.bot.get_guild(guild_id)
        if guild:
            self.channels = [(channel.name, channel.id) for channel in guild.text_channels]
            self.update_buttons()

    def update_buttons(self):
        self.channel_layout.clear_widgets()
        for channel in self.channels:
            button = Button(text=channel[0], size_hint_y=None, height=50)
            button.bind(on_press=self.toggle_button)
            self.channel_layout.add_widget(button)
        self.listen_button.disabled = False

    def toggle_button(self, instance):
        if self.selected_channel:
            self.selected_channel.background_color = (1, 1, 1, 1)
        instance.background_color = (0, 0, 0, 1)
        self.selected_channel = instance
        self.match_channel = next(channel[1] for channel in self.channels if channel[0] == instance.text)

    def listen_server(self, instance):
        if self.match_channel:
            threading.Thread(target=self._listen_server).start()

    def _listen_server(self):
        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
            sock.connect(('localhost', 12345))