#!/usr/bin/python
''' handle gui commands '''
import ri_tk as display
import ri_widget
import ri_data
import ri_dep
import ri_func_dep
import ri_oper
import re
import copy
import sys

def serial_no_init():
    if ri_data.SerialNumber.value.strip():
        display.var_dict['serial_no.number'].set(value=ri_data.SerialNumber.value)

def serial_no_quit():
    ri_data.SerialNumber.value = display.var_dict['serial_no.number'].get()

def mount_list_init():
    ''' initialize mount list '''
    l = []
    ri_data.MountPoint.init_from_internal()
    M_keys = ri_data.MountPoint.dict.keys()
    M_keys.sort()
    for d in M_keys:
        # get size from Partition info
        sz = ri_data.MountPoint.get_size(d)
        m = ri_data.MountPoint.dict[d]
        s = m.device.ljust(10) + m.directory.ljust(10) + m.filesystem.ljust(10) + m.format.ljust(4) + sz.ljust(6) + ri_data.Partition.unit
        l.append(s)
    display.var_dict['mount.list'].set(value=tuple([str(i) for i in l]))
    ''' if disk has no partition, do this '''
    ret = ri_data.Partition.check_partitions()
    if ret != 0 and not ri_widget.MessageBox.dict["check_partitions"].show():
        sys.exit(1)

def mount_quit():
    if ri_oper.Operation.getarch() == "ia64":
        for (key,value) in ri_data.MountPoint.dict.items():
            if (value.directory,value.filesystem,value.format) == ("/tmppoint","vfat","yes"):
                return 
        ri_widget.MessageBox.dict['check_special_mount'].show()
        ri_widget.Sequence.previous()

def mount_list_modify(*args):
    ''' modify an item in mount list '''
    tw = ri_widget.TopWindow.dict['mount_list_modify']
    tw.show()

def mp_top_init():
    ''' mount dir top window initialize '''
    ml_win = ri_widget.Widget.dict['mount.list'].tk_widget
    idxs = ml_win.curselection()
    if len(idxs) == 1:
        idx = int(idxs[0])
        l = eval(display.var_dict['mount.list'].get())
        dev = l[idx].split()[0]
        mp = ri_data.MountPoint.dict[dev]
        dr = mp.directory
        fs  = mp.filesystem
        fm  = mp.format
        sz  = ri_data.MountPoint.get_size(dev)
        display.var_dict['mp_top_dev'].set(value=dev)
        display.var_dict['mp_top_size'].set(value=sz)
        display.var_dict['mp_top_dir'].set(value=dr)
        if fm == 'yes':
            ri_widget.Widget.dict['mp_top_format'].tk_widget.select()
        else:
            ri_widget.Widget.dict['mp_top_not_format'].tk_widget.select()

        fs_values = eval(display.var_dict['mp_top_fs'].get())
        for i in range(len(fs_values)):
            if fs == fs_values[i]:
                ri_widget.Widget.dict['mp_top_fs'].tk_widget.selection_set(i)


def mp_top_ok():
    ''' mount dir top window OK '''
    l = []
    for itm in eval(display.var_dict['mount.list'].get()):
        dev = itm.split()[0]
        dev2 = display.var_dict['mp_top_dev'].get()
        if dev == dev2:
            sz  = display.var_dict['mp_top_size'].get()
            dr = display.var_dict['mp_top_dir'].get()
            fm  = display.var_dict['mp_top_format'].get()
            idxs2 = ri_widget.Widget.dict['mp_top_fs'].tk_widget.curselection()
            if len(idxs2) and fm =='yes' :
                # if format, use the filesystem just set
                idx2  = int(idxs2[0])
                fs    = eval(display.var_dict['mp_top_fs'].get())[idx2]
            elif dev in ri_data.Partition.dict.keys():
                # else use the filesystem in Partition
                fs = ri_data.Partition.dict[dev].filesystem
            else:
                fs = ' '

            # check mount point is feasible or not
            isdir_feasible = ri_data.MountPoint.check_data(dev,dr,fs)
            if isdir_feasible:
                s2 = dev.ljust(10) + dr.ljust(10) + fs.ljust(10) + fm.ljust(4) + sz.ljust(6) + ri_data.Partition.unit
                ri_data.MountPoint.change(dev, dr, fs, fm)
                l.append(s2)
            else:
                l.append(itm)
        else:
            l.append(itm)

    display.var_dict['mount.list'].set(value=tuple(l))
    ri_widget.TopWindow.dict['mount_list_modify'].hide()
    if not isdir_feasible:
        ri_widget.MessageBox.dict['check_mount_point'].show()

def mp_top_cancel():
    ''' mount dir top window cancel '''
    ri_widget.TopWindow.dict['mount_list_modify'].hide()


def network_init():
    ''' network initialize '''
    if ri_data.Network.hostname.strip():
        display.var_dict['network_host_name'].    set(value=ri_data.Network.hostname)
    ri_widget.Widget.dict['network_config_%s' %(ri_data.Network.configuration and ri_data.Network.configuration or 'static')].tk_widget.invoke()
    display.var_dict['network_domain_name'].  set(value=ri_data.Network.domain)
    display.var_dict['network_ip'].           set(value=ri_data.Network.ip)
    display.var_dict['network_subnet_mask'].  set(value=ri_data.Network.mask)
    display.var_dict['network_gateway'].      set(value=ri_data.Network.gateway)
    display.var_dict['network_primary_dns'].  set(value=ri_data.Network.primary_dns)
    display.var_dict['network_secondary_dns'].set(value=ri_data.Network.secondary_dns)

def check_address(n):
	if (re.match("^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$",n) and \
			len([i for i in n.split('.') if (0<= int(i) <=255)])==4):
		return True
	else:
		return False

def network_quit():
    ''' network quit '''
    ri_data.Network.hostname       = display.var_dict['network_host_name'].get()
    ri_data.Network.configuration  = display.var_dict['network_config_method'].get()
    ri_data.Network.domain         = display.var_dict['network_domain_name'].get()
    ri_data.Network.ip             = display.var_dict['network_ip'].get()
    ri_data.Network.mask           = display.var_dict['network_subnet_mask'].get()
    ri_data.Network.gateway        = display.var_dict['network_gateway'].get()
    ri_data.Network.primary_dns    = display.var_dict['network_primary_dns'].get()
    ri_data.Network.secondary_dns  = display.var_dict['network_secondary_dns'].get()

    if not ri_data.Network.hostname:
        ri_widget.MessageBox.dict['check_ip_hostname'].show()
        ri_widget.Sequence.previous()
    elif (ri_data.Network.configuration == "static" and \
			((not check_address(ri_data.Network.ip) )or \
			 (not check_address(ri_data.Network.mask) )or \
			 (not check_address(ri_data.Network.gateway) )or \
			 (not check_address(ri_data.Network.primary_dns)) ) ):
        ri_widget.MessageBox.dict['check_ip_hostname'].show()
        ri_widget.Sequence.previous()
		#IP		0.0.0.0--255.255.255.255

def ncm_dynamic():
    ''' when radio button ncm dynamic is checked, several data entry will be set 'disable' '''
    
    for n in ('network_domain_name','network_ip','network_subnet_mask','network_gateway','network_primary_dns','network_secondary_dns'):
        ri_widget.Widget.dict[n].tk_widget.configure(state='disable')

def ncm_static():
    ''' when radio button ncm static is checked, several data entry will be set 'normal' '''
    for n in ('network_domain_name','network_ip','network_subnet_mask','network_gateway','network_primary_dns','network_secondary_dns'):
        ri_widget.Widget.dict[n].tk_widget.configure(state='normal')

class GroupButton(object):
    ''' A function class called whenever the group button is clicked '''
    dict={}
    def __init__(self, g):
        self.name = g.name
        self.win  = display.SoftwarePackageWindow(g)
        GroupButton.dict[g.name] = self


    def __call__(self):
        self.win.show()

class GroupCheck(GroupButton):
    ''' A function class called whenever the group check button is checked '''
    def __init__(self, g, v):
        self.variable = v
        GroupButton.__init__(self, g)

    def __call__(self):
        v = display.var_dict[self.variable]
        if v.get() == 'yes':
            display.SoftwarePackageWindow.dict[self.name].show()

def software_group_mandatory_construct(w):
    ''' construct widgets based actual data
w - Widget instance '''
    mdt = [ m for m in ri_data.Group.dict.values() if m.install == 'mandatory' ]
    wit = w.widgets.pop()
    for i in mdt:
        wi = copy.deepcopy(wit)
        wi.attr['text'] = i.name
        vn = "software_group_%s" %(i.name)
        idx = mdt.index(i)
        wi.grid_location.dict['column'] = idx % int(w.grid_management.columns)
        wi.grid_location.dict['row']    = idx / int(w.grid_management.columns)
        gc = GroupButton(i)
        setattr(sys.modules['ri_cmd'], vn, gc)
        wi.attr['command'] = vn
        w.add_sub_widget(wi)

def software_group_optional_construct(w):
    ''' construct widgets based actual data
w - Widget instance '''
    opt = [ o for o in ri_data.Group.dict.values() if o.install != 'mandatory' ]
    wit = w.widgets.pop()
    for i in opt:
        wi = copy.deepcopy(wit)
        wi.attr['text'] = i.name
        vn = "software_group_%s" %(i.name)
        idx = opt.index(i)
        wi.grid_location.dict['column'] = idx % int(w.grid_management.columns)
        wi.grid_location.dict['row']    = idx / int(w.grid_management.columns)
        gc = GroupCheck(i, vn)
        setattr(sys.modules['ri_cmd'], vn, gc)
        wi.attr['command'] = vn
        wi.attr['variable'] = vn
        wi.variables = [(vn, 'StringVar', i.install),]
        w.add_sub_widget(wi)

def software_group_optional_quit():
    ''' software group window quit, record optional group state '''
    opt = [ o for o in ri_data.Group.dict.values() if o.install != 'mandatory' ]
    for i in opt:
        vn = "software_group_%s" %(i.name)
        i.install = display.var_dict[vn].get()

def dependency_fun_pkg_display():
    ''' init function for list in dependency step '''
    ri_dep.dependency_init()
    f_dep_text = ["function dependency list"]
    f = [ k.ljust(30) + ': ' + ri_dep.dependency_init.func_dep_dict[k] for k in ri_dep.dependency_init.func_dep_dict.keys() ]

    dep_text = ["package dependency list"]
    l = [ k.ljust(20) + ': ' + ' '.join(ri_dep.dependency_init.dep_dict[k]) for k in ri_dep.dependency_init.dep_dict.keys()]

    l = f_dep_text + f + dep_text + l
    display.var_dict['dependency.list'].set(value=tuple(l))
    
def service_construct(w):
    ''' construct service widget based on actual data
w - Widget instance '''

    # first refresh service state
    wit = w.widgets.pop()
    for i in ri_data.Service.list:
        wi = copy.deepcopy(wit)
        vn = "service_%s" %(i.name)
        # process widget name
        wi.name = vn
        ri_widget.Widget.dict[vn] = wi
        wi.attr['text'] = i.name
        wi.attr['variable'] = vn
        wi.variables = [(vn, 'StringVar', '')]
        idx = ri_data.Service.list.index(i)
        wi.grid_location.dict['column'] = idx % int(w.grid_management.columns)
        wi.grid_location.dict['row']    = idx / int(w.grid_management.columns)
        w.add_sub_widget(wi)

def service_init():
    ''' initialize service checkboxes, based on package selection '''
    # first refresh service state
    ri_data.Service.change_state()
    for i in ri_data.Service.list:
        vn = "service_%s" %(i.name)
        win = ri_widget.Widget.dict[vn].tk_widget
        if i.start == 'disable':
            win.configure(state = 'disable')
        display.var_dict[vn].set(value=i.start=='yes' and 'yes' or 'no')

def service_quit():
    ''' record service state '''
    for i in ri_data.Service.list:
        if i.start != 'disable':
            vn = "service_%s" %(i.name)
            i.start = display.var_dict[vn].get()

def raid_raw_init():
    ''' initialize raid raw devices (parttion with id 'fd' '''
    global raid_raw_initialized
    if not raid_raw_initialized:
        raid_raw_initialized = True
        # get all component devices already in raid
        dev_in_raid = ri_data.Raid.dev_in_raid()

        raw_devs = [ d for d in ri_data.Partition.dict.keys() 
                     if re.search('raid', ri_data.Partition.dict[d].flags) and d not in dev_in_raid ]
        raw_devs.sort()
        display.var_dict['raid_raw_devs'].set(value=tuple(raw_devs))

def list_to_list(list_from, var_from, var_to):
    ''' move item from list a to list b '''
    win_from = ri_widget.Widget.dict[list_from].tk_widget
    idxs = win_from.curselection()
    if len(idxs) == 1:
        idx = int(idxs[0])
        l_fr = list(eval(display.var_dict[var_from].get()))
        itm = l_fr[idx]
        del l_fr[idx]
        display.var_dict[var_from].set(value=tuple(l_fr))
        if display.var_dict[var_to].get():
            l_to = list(eval(display.var_dict[var_to].get()))
            l_to.append(itm)
        else:
            l_to = [ itm ]
            l_to.sort()
        display.var_dict[var_to].set(value=tuple(l_to))
    
def raid_raw_to_active():
    ''' move device from raw to active '''
    list_to_list('raid_raw.list', 'raid_raw_devs', 'raid_active_devs')

def raid_active_to_raw():
    ''' move device from active to raw '''
    list_to_list('raid_active.list', 'raid_active_devs', 'raid_raw_devs')

def raid_raw_to_spare():
    ''' move device from raw to spare '''
    list_to_list('raid_raw.list', 'raid_raw_devs', 'raid_spare_devs')

def raid_spare_to_raw():
    ''' move device from spare to raw '''
    list_to_list('raid_spare.list', 'raid_spare_devs', 'raid_raw_devs')

def raid_device_init():
    ''' initialize raid device list '''
    raid_devs = [ k for k in ri_data.Raid.dict.keys() ]
    raid_devs.sort()
    if not raid_devs:
        raid_devs=[]

    display.var_dict['raid_devs'].set(value=tuple(raid_devs))

def raid_device_add():
    ''' add a new raid device '''
    try:
        active = list(eval(display.var_dict['raid_active_devs'].get()))
    except:
        active = []

    try:
        spare  = list(eval(display.var_dict['raid_spare_devs'].get()))
    except:
        spare = []

    level  = display.var_dict['raid_level'].get()

    if not active or not level:
        ri_widget.MessageBox.dict["raid_add_warning"].show()
        return
    elif int(level) < 2 and len(active) < 2:
        ri_widget.MessageBox.dict["raid_add_active_numbers"].show()
        return 
    elif str(level) == "5" and len(active)<3:
        ri_widget.MessageBox.dict["raid_add_active_numbers_2"].show()
        return 

    dev = ri_data.Raid.get_next_device()
    ri_data.Raid(dev, "no", level, active, spare)
    raid_device_init()
    display.var_dict['raid_active_devs'].set(value='')
    display.var_dict['raid_spare_devs'].set(value='')
    ri_widget.Widget.dict['raid_level_0'].tk_widget.deselect()
    ri_widget.Widget.dict['raid_level_1'].tk_widget.deselect()
    ri_widget.Widget.dict['raid_level_5'].tk_widget.deselect()

def raid_device_delete():
    ''' delete a raid device, put its component devices into active/spare device list '''
    win_dev = ri_widget.Widget.dict['raid_dev.list'].tk_widget
    idxs = win_dev.curselection()
    if len(idxs) == 1:
        idx = int(idxs[0])
        try:
            l = eval(display.var_dict['raid_devs'].get())
        except:
            # a null string? 
            return
        dev = l[idx].split()[0]
        r = ri_data.Raid.dict[dev]
        if r.from_os == 'yes':
            ri_widget.MessageBox.dict["raid_delete_warning"].show()
            return
        try:
            active = list(eval(display.var_dict['raid_active_devs'].get()))
        except:
            active=[]
        try:
            spare  = list(eval(display.var_dict['raid_spare_devs'].get()))
        except:
            spare=[]
        active.extend(r.active_components)
        spare.extend(r.spare_components)
        # do not touch level
        display.var_dict['raid_active_devs'].set(value=tuple(active))
        display.var_dict['raid_spare_devs'].set(value=tuple(spare))
        del ri_data.Raid.dict[dev]
        raid_device_init()

def raid_device_list_detail(*args):
    ''' show details of a raid device '''
    win = ri_widget.Widget.dict['raid_dev.list'].tk_widget
    idxs = win.curselection()
    if len(idxs) == 1:
        idx = int(idxs[0])
        try:
            l = eval(display.var_dict['raid_devs'].get())
        except:
            # a null string? 
            return
        dev = l[idx].split()[0]
        r = ri_data.Raid.dict[dev]
        display.var_dict['raid_detail_active'].set(value='active: %s' %(str(r.active_components)))
        display.var_dict['raid_detail_spare'].set(value='spare: %s' %(str(r.spare_components)))
        display.var_dict['raid_detail_level'].set(value='level: %s' %(str(r.level)))

def prepar_installation_init():
    '''install information initialize'''
    ins_info = ri_data.prepar_installation()
    t= ri_widget.Widget.dict['prepar_installation.text'].tk_widget
    t.configure(state='normal')
    t.insert(1.0,ins_info)
    t.configure(state='disable')

raid_raw_initialized = False
