from window import Window 
from windowstringreader import WindowStringReader
from textpane import TextPane
from readmultext import ReadMulText
from confirmwindow import ConfirmWindow
from actionresult import ActionResult
from device import Device

class PartitionISO(object):
    def __init__(self, maxy, maxx, install_config):
        self.maxx = maxx
        self.maxy = maxy
        self.win_width = maxx - 4
        self.win_height = maxy - 4
        self.install_config = install_config
        self.path_checker = []

        self.win_starty = (self.maxy - self.win_height) / 2
        self.win_startx = (self.maxx - self.win_width) / 2

        self.text_starty = self.win_starty + 4
        self.text_height = self.win_height - 6
        self.text_width = self.win_width - 6
        self.install_config['partitionsnumber'] = 0
        self.devices = Device.refresh_devices_bytes()
        self.has_slash = False
        self.has_remain = False
        self.has_empty = False

        self.disk_size = []
        for index, device in enumerate(self.devices):
            self.disk_size.append((device.path, int(device.size) / 1048576))     

        self.window = Window(self.win_height, self.win_width, self.maxy, self.maxx, 'Welcome to the Photon installer', False, items=[], can_go_next=False)
        Device.refresh_devices()

    def display(self, params):
        if 'skipPrevs' in self.install_config and self.install_config['skipPrevs'] == True:
            self.delete()
            return ActionResult(False, {'goBack':True})
        if 'autopartition' in self.install_config and self.install_config['autopartition'] == True:
            return ActionResult(True, None)
        if 'delete_partition' in self.install_config and self.install_config['delete_partition'] == True:
            self.delete()
            self.install_config['delete_partition']=False

        self.device_index = self.install_config['diskindex']

        self.disk_buttom_items = []
        self.disk_buttom_items.append(('<Next>', self.next))
        self.disk_buttom_items.append(('<Create New>', self.create_function))
        self.disk_buttom_items.append(('<Delete All>', self.delete_function))
        self.disk_buttom_items.append(('<Go Back>', self.go_back))

        self.text_items = []
        self.text_items.append(('Disk', 20))
        self.text_items.append(('Size', 5))
        self.text_items.append(('Type', 5))
        self.text_items.append(('Mountpoint', 20))
        self.table_space = 5

        title = 'Current partitions:\n'
        self.window.addstr(0, (self.win_width - len(title)) / 2, title)

        info = "Unpartitioned space: "+str(self.disk_size[self.device_index][1])+ " MB, Total size: "+ str(int(self.devices[self.device_index].size)/ 1048576)+" MB"

        self.text_pane = TextPane(self.text_starty, self.maxx, self.text_width, 
            "EULA.txt", self.text_height, self.disk_buttom_items, 
            partition = True, popupWindow = True, install_config = self.install_config, 
            text_items = self.text_items, table_space=self.table_space, default_start=1, info=info, size_left=str(self.disk_size[self.device_index][1]))

        self.window.set_action_panel(self.text_pane)

        return self.window.do_action()

    def validate_partition(self, pstr):
        if not pstr:
            return ActionResult(False, None)
        sizedata = pstr[0]
        mtdata = pstr[2]
        typedata = pstr[1]
        devicedata = self.devices[self.device_index].path

        #no empty fields unless swap
        if typedata == 'swap' and (len(mtdata)!=0 or len(typedata) == 0 or len(devicedata) == 0):
            return False, "invalid swap data "

        if typedata != 'swap' and (len(sizedata) == 0 or len(mtdata) == 0 or len(typedata) == 0 or len(devicedata) == 0):
            if not self.has_empty and len(mtdata) != 0 and len(typedata) != 0 and len(devicedata) != 0:
                self.has_empty = True
            else:
                return False, "Input cannot be empty"

        if typedata !='swap' and typedata!='ext3' and typedata!='ext4':
            return False, "Invalid type"

        if len(mtdata)!=0 and mtdata[0] !='/':
            return False, "Invalid path"

        if mtdata in self.path_checker:
            return False, "Path already existed"
        #validate disk: must be one of the existing disks
        i = self.device_index

        #valid size: must not exceed memory limit
        curr_size = self.disk_size[i][1]
        if len(sizedata)!=0:
            try:
                int(sizedata)
            except ValueError:
                return False, "invalid device size"

            if int(curr_size) - int(sizedata) < 0:
                return False, "invalid device size"
            #if valid, update the size and return true
            new_size = (self.disk_size[i][0], int(curr_size)- int(sizedata))
            self.disk_size[i] =new_size

        if mtdata=="/":
            self.has_slash=True

        self.path_checker.append(mtdata)
        return True, None

    def create_function(self):
        self.window.hide_window()

        self.install_config['partition_disk'] = self.devices[self.device_index].path
        self.partition_items = []
        self.partition_items.append(('Size in MB: '+str(self.disk_size[self.device_index][1])+' available'))
        self.partition_items.append(('Type: (ext3, ext4, swap)'))
        self.partition_items.append(('Mountpoint:'))
        self.create_window = ReadMulText(
                self.maxy, self.maxx, 0,
                self.install_config,
                str(self.install_config['partitionsnumber']) + 'partition_info',
                self.partition_items,
                None,
                None,
                None,
                self.validate_partition,   #validation function of the input
                None,
                True,
                )
        result = self.create_window.do_action()
        if result.success:
            self.install_config['partitionsnumber'] = self.install_config['partitionsnumber'] + 1

        #parse the input in install config
        return self.display(False)

    def delete_function(self):
        self.delete()
        return self.display(False)

    def go_back(self):
        self.delete()
        self.window.hide_window()
        self.text_pane.hide()
        return ActionResult(False, {'goBack':True})

    def next(self):
        if self.install_config['partitionsnumber'] == 0:
            window_height=9
            window_width=40
            window_starty=(self.maxy-window_height)/2+5
            confirm_window=ConfirmWindow(window_height,window_width,self.maxy, self.maxx, window_starty, 'Partition information cannot be empty', info=True)
            confirm_window.do_action()
            return self.display(False)
        #must have /
        if not self.has_slash:
            window_height=9
            window_width=40
            window_starty=(self.maxy-window_height)/2+5
            confirm_window=ConfirmWindow(window_height,window_width,self.maxy, self.maxx, window_starty, 'Missing /', info=True)
            confirm_window.do_action()
            return self.display(False)

        self.window.hide_window()
        self.text_pane.hide()
        return ActionResult(True, {'goNext':True})

    def delete(self):
        for i in range(int(self.install_config['partitionsnumber'])):
            self.install_config[str(i)+'partition_info'+str(0)] = ''
            self.install_config[str(i)+'partition_info'+str(1)] = ''
            self.install_config[str(i)+'partition_info'+str(2)] = ''
            self.install_config[str(i)+'partition_info'+str(3)] = ''
        del self.disk_size[:]
        for index, device in enumerate(self.devices):
            self.disk_size.append((device.path, int(device.size) / 1048576))
        del self.path_checker[:]
        self.has_slash = False
        self.has_remain = False
        self.has_empty = False
        self.install_config['partitionsnumber'] = 0