import wx
from modules.gui.PyCSI import DialogServerSetupGui
from modules.server.server import UploadServer
from modules.gui.panel_button import Button
from modules.gui.qr_code import QRCode
import socket

class DialogServerSetup(DialogServerSetupGui):

  def __init__(self, parent, scene_dir):
    super().__init__(parent)

    self.ip = self.get_ipv4_address()
    self.port = self.find_available_port()
    self.qr_code_bitmap = QRCode(self, 
                          self.ip + ":" + str(self.port), 
                          box_size=10, 
                          border=2.5)

    self.SetDoubleBuffered(True)
    self.connection_animation = {
      0: "Open for upload.  ",
      1: "Open for upload.. ",
      2: "Open for upload..."
    }
    self.server_thread = UploadServer(scene_dir, self.ip, self.port)

    self.message = "Server established. Connection open."
    self.anim_counter = 0

    button_font = wx.Font(14, wx.FONTFAMILY_SWISS, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD, False, "Calibri Bold")
    w, h = self.GetSize()
    sizer = wx.BoxSizer(wx.VERTICAL)
    sizer.Add((0,0), 1, wx.EXPAND| wx.ALL, 5)

    
    self.terminate_button = Button(parent = self,
                                    label = "End Capture",
                                    background= wx.Colour(45, 45, 45),
                                    font = button_font,
                                    radius = 10,
                                    id = wx.ID_ANY,
                                    pos = wx.DefaultPosition,
                                    size = wx.Size(300,50),
                                    color=0,
                                    font_color=[255, 255, 255])
    
    term_sizer = wx.BoxSizer(wx.HORIZONTAL)
    term_sizer.Add((0,0), 1, wx.EXPAND| wx.ALL, 5)
    term_sizer.Add(self.terminate_button, 0, wx.EXPAND| wx.ALL, 5)
    term_sizer.Add((0,0), 1, wx.EXPAND| wx.ALL, 5)
    sizer.Add(term_sizer, 0, wx.EXPAND|wx.ALL, 5)
    self.SetSizer(sizer)
    self.Layout()

    self.timer = wx.Timer(self)
    self.Bind(wx.EVT_TIMER, self.on_timer, self.timer)
    self.timer.Start(500)
    
    self.terminate_button.Bind(wx.EVT_LEFT_UP, self.terminate_server)
    self.Bind(wx.EVT_PAINT, self.on_paint)
    self.Bind(wx.EVT_CLOSE, self.on_close)

  def get_ipv4_address(self):
    hostname = socket.gethostname()
    ip_address = socket.gethostbyname(hostname)
    return ip_address

  def find_available_port(self):
      sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
      sock.bind(('', 0))
      port = sock.getsockname()[1]
      sock.close()
      return port
  
  def terminate_server(self, event):
    self.server_thread.terminate_server()
    
  def on_paint(self, event):
    
    dc = wx.BufferedPaintDC(self)
    gc = wx.GraphicsContext.Create(dc)
    gc.SetAntialiasMode(wx.ANTIALIAS_DEFAULT)
    dc.Clear()

    w, h = self.GetSize()

    text = f"Scan QR Code to Start Upload"
    font = wx.Font(28, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD)
    gc.SetFont(font, wx.Colour(233, 233, 233))
    text_width_ip, text_height_ip = gc.GetTextExtent(text)
    
    x = (w - text_width_ip) / 2
    y = 25
    #y = ((h - text_height_ip) / 2) -25

    gc.DrawText(text, x, y)

    qr_bitmap_width, qr_bitmap_height = self.qr_code_bitmap.GetSize()

    padding = 10
    rectWidth = qr_bitmap_width + (2 * padding)
    rectHeight = qr_bitmap_height + (2 * padding)

    posX = (self.GetSize().width - rectWidth) // 2
    posY = (self.GetSize().height - rectHeight) // 2
    
    radius = 20 
    gc.SetBrush(wx.Brush("white")) 
    gc.SetPen(wx.Pen("black", 6))
    gc.DrawRoundedRectangle(posX-6, posY, rectWidth, rectHeight, radius)
    
    qr_x = (w - qr_bitmap_width) / 2
    qr_y = (h - qr_bitmap_height) / 2
    gc.DrawBitmap(self.qr_code_bitmap, qr_x-6, qr_y, qr_bitmap_width, qr_bitmap_height)

    

  def on_timer(self, event):
    self.anim_counter += 1
    if self.anim_counter == 3:
      self.anim_counter = 0
    self.current_anim = self.connection_animation[self.anim_counter]
    

    self.Freeze()
    self.Refresh()
    self.Thaw() 
    if not self.server_thread.is_running():
      self.EndModal(wx.ID_OK)
      self.timer.Stop()
  
  def on_close(self, event):
    event.Skip()