import sys
import os
import turtle
import serial
import math

class I_Ching:
    def __init__(self):
        self.serial_port = None
        self.my_turtle = None
        self.select_com = None
        self.lines, self.line_width = 6, 50
        self.heading_value = 0
        self.width_s = 0
        self.height_s = 0
        self.i = 1
        self.y_pos = 0
        self.lines_number = [6, 18]
        self.total,self.x = 0,0

    @staticmethod
    def get_available_serial_coms():
        if sys.platform.startswith('win'):
            available_coms = []
            for i in range(256):
                com_port = f'COM{i + 1}'
                try:
                    with serial.Serial(com_port):
                        available_coms.append(com_port)
                except (OSError, serial.SerialException):
                    pass
            return available_coms
        else:
            raise EnvironmentError('Unsupported platform')

    @staticmethod
    def input_choice(prompt, choices):
        while True:
            try:
                for index, choice in enumerate(choices):
                    print(index, "-", choice)
                user_input = int(input(f"Please select your {prompt}: "))
                selected_choice = choices[user_input]
                print(f"You selected: {selected_choice}")
                return selected_choice
            except:
                print("Invalid input. Try again.")

    def connect_serial(self, com_name):
        try:
            self.serial_port = serial.Serial(com_name, 9600, timeout=0)
            print(f"Serial connected on {com_name} successfully ^-*")
        except:
            print("COM port busy or does not exist ^-^")


    def draw_line(self, value):
        reminder = value % 2
        if reminder == 0:
            output = 'broken line'
        else:
            output = 'solid line'
        print('<<<< ','Index : ',self.i,', Random Number : ',value,', Reminder : ', reminder,', Line Output : ',output,' >>>>')
        if self.i == 1:
            self.my_turtle.setposition(self.width_s/-2,self.height_s/2)
            self.y_pos = self.height_s/2
             
        if value % 2:
            self.my_turtle.pendown()
            self.my_turtle.fd(self.width_s)
            self.my_turtle.penup()
        else:
            self.my_turtle.pendown()
            self.my_turtle.fd(self.width_s/2-100)
            self.my_turtle.penup()
            self.my_turtle.setposition(100,self.y_pos)
            self.my_turtle.pendown()
            self.my_turtle.fd(self.width_s/2 - 100)
            self.my_turtle.penup()
            
            
        self.my_turtle.setposition(self.width_s/-2,self.height_s/2-self.i*(self.height_s/(6-1)))
        self.y_pos = self.height_s/2-self.i*(self.height_s/(6-1))
        
        if self.i == 6:
            self.i = 1
            while True:
                user_input = input("Do you want to continue? (yes/no): ")
                if user_input.lower() in ["yes", "y"]:
                    print("Continuing...")
                    self.serial_port.reset_input_buffer()  # Clear serial buffer
                    self.my_turtle.clear()
                    self.graphic_screen_on_top()
                    break
                elif user_input.lower() in ["no", "n"]:
                    print("Exiting...")
                    os._exit(0)
                    break
                else:
                    print("Invalid input. Please enter yes/no.")
        else:
            self.i += 1
        

    def update_turtle(self):
        if self.serial_port and self.serial_port.is_open and self.serial_port.inWaiting() >= 1:
            byte_read = self.serial_port.read()
            random_number = int.from_bytes(byte_read, byteorder='big')
            if 0 <= random_number <= 255:
                if self.lines == 6 :
                    self.draw_line(random_number)
                else:
                    self.x+=1
                    self.total+= random_number
                    print('Index : ',self.x,', Random Number : ' ,random_number,', Total : ', self.total)
                    if self.x==3:
                        self.draw_line(self.total)
                        self.total,self.x = 0,0


        turtle.ontimer(self.update_turtle, 1000)

    def graphic_screen_on_top(self):
        rootwindow = turtle.getcanvas().winfo_toplevel()
        rootwindow.call('wm', 'attributes', '.', '-topmost', '1')
        rootwindow.call('wm', 'attributes', '.', '-topmost', '0')
        
    def main(self):
        self.select_com = self.input_choice("com port to connect with random number", self.get_available_serial_coms())
        self.lines = float(self.input_choice("Select lines number", self.lines_number))

        self.width_s = turtle.window_width() - 100
        self.height_s = turtle.window_height() - 200
        self.y_pos = self.height_s/2
        
        self.my_turtle = turtle.Turtle()
        self.graphic_screen_on_top()
        self.my_turtle.width(self.line_width)
        self.my_turtle.hideturtle()
        self.my_turtle.setheading(0)
        self.my_turtle.penup()
        self.my_turtle.setposition(self.width_s/-2,self.height_s/2)
                
        self.connect_serial(self.select_com)
        self.update_turtle()

        turtle.mainloop()


instance = I_Ching()
instance.main()
