#-*- coding: utf-8 -*-

# Copyright 2010-2012 Calculate Ltd. http://www.calculate-linux.org
#
#  Licensed under the Apache License, Version 2.0 (the "License");
#  you may not use this file except in compliance with the License.
#  You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
#  Unless required by applicable law or agreed to in writing, software
#  distributed under the License is distributed on an "AS IS" BASIS,
#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#  See the License for the specific language governing permissions and
#  limitations under the License.

import soaplib, sys, time, os
import threading

from soaplib.serializers.primitive import String, Integer, Any, Boolean
from soaplib.serializers.clazz import Array
from soaplib.service import rpc, DefinitionBase
from calculate.core.server.api_types import ReturnedMessage,CommonInfo
from calculate.core.server.api_types import ChoiceValue, Table, Option, Field, \
                                           GroupField, ViewInfo, ViewParams
from calculate.lib.datavars import VariableError,DataVarsError
from calculate.install.cl_install import InstallError

#from cl_install import Install,DataVarsInstall
import cl_install
from calculate.lib.cl_lang import setLocalTranslate,getLazyLocalTranslate
from calculate.core.server.decorators import Dec
from calculate.core.server.func import catchExcept,commonView
core_method = Dec.core_method
setLocalTranslate('cl_install3',sys.modules[__name__])
import traceback
from functools import wraps,WRAPPER_ASSIGNMENTS

__ = getLazyLocalTranslate(_)


class InstallInfo(CommonInfo):
    """Parameters for method install"""
    cl_image_filename = String
    cl_image_linux_shortname = String
    cl_image_arch_machine = String
    cl_image_linux_ver = String
    cl_image_linux_build = String

    os_install_disk_single = String
    os_location_data = Array(Array(String))
    os_install_mbr = Array(String)
    os_install_root_type = String
    os_install_scratch = Boolean
    cl_uuid_set = Boolean
    os_install_kernel_scheduler = String

    os_install_locale_lang = String
    os_install_clock_timezone = String

    cl_migrate_root_pwd = String
    cl_migrate_data = Array(Array(String))
    cl_autologin = String
    os_install_net_fqdn = String
    os_install_net_data = Array(Array(String))
    os_install_net_route_data = Array(Array(String))
    os_install_net_conf = String
    os_install_net_dns = String
    os_install_net_dns_search = String
    os_install_ntp = String
    os_install_x11_video_drv = String
    os_install_x11_resolution = String
    os_install_x11_composite = Boolean
    os_install_fb_resolution = String

    cl_autopartition_device = Array(String)
    cl_autopartition_scheme = Array(String)
    cl_autopartition_set = Boolean
    cl_autopartition_table = String
    cl_autopartition_root_size = String

    cl_live = Boolean
    os_install_pxe = Boolean
    os_install_pxe_path = String

installCatchExcept = catchExcept(VariableError,DataVarsError,
                                 cl_install.InstallError)

class Wsdl:
    from calculate.core.server.baseClass import Basic
    from calculate.core.server.decorators import Dec

    @rpc(Integer, InstallInfo, _returns = Array(ReturnedMessage))
    @core_method(category=__('Installation'),title=__("System install"),
        image='calculate-install,system-installer,applications-other,'
              'drive-harddisk',
        gui=True,command='cl-install',
        rights=['install'])
    def install ( self, sid, info):
        return self.callMethod(sid,info,logicClass=cl_install.Install,
                               method="installSystem",method_name="install",
                               callbackRefresh=self.fixInstallLocalization)

    def install_vars(self,dv=None):
        if not dv:
            dv = cl_install.DataVarsInstall()
            dv.importInstall()
            dv.flIniFile()
            dv.Set('cl_action','system',True)
            dv.Set('cl_dispatch_conf','usenew',True)
        dv.addGroup(_("Language and locale"),
            image="welcome",
            normal=('os_install_locale_lang','os_install_clock_timezone'))
        dv.addGroup(_("Distribution"),
            normal=('cl_image_filename',),
            expert=('cl_image_linux_shortname', 'cl_image_arch_machine'))
        dv.addGroup(_("Allocate drive space"),
            normal=('cl_autopartition_set',),
            expert=('cl_autopartition_scheme','cl_autopartition_device',
                    'cl_autopartition_table','cl_autopartition_root_size'),
            expert_label=_("Click to set up autopartition options"))
        dv.addGroup(_("Mount points"),
            normal=('os_location_data',),
            brief=('os_location_data','os_install_mbr'),
            expert=('os_install_scratch','cl_uuid_set',
                    'os_install_root_type','os_install_mbr',
                    'os_install_kernel_scheduler'))
        dv.addGroup(_("Network settings"),
            normal=('os_install_net_conf','os_install_net_data',
                    'os_install_net_fqdn','os_install_ntp'),
            expert=('os_install_net_dns','os_install_net_dns_search',
                    'os_install_net_route_data',))
        dv.addGroup(_("Users"),
            normal=('cl_migrate_root_pwd','cl_migrate_data','cl_autologin'),
            hide=('cl_migrate_data',),
            brief=('cl_migrate_user',))
        dv.addGroup(_("Video"),
            normal=('os_install_x11_video_drv','os_install_x11_composite',
                    'os_install_x11_resolution','os_install_fb_resolution'))
        dv.addBrief(next_label=_("Installation"),image="finish")
        return dv

    def fixInstallLocalization(self,sid,dv):
        """
        Fix localization on change lang in install method
        """
        curThread = threading.currentThread()
        curThread.lang = dv.Get('os_install_locale_lang')
        currentLang = self.get_cache(sid,"install","lang")
        if currentLang != curThread.lang:
            dv.clearGroups()
            self.install_vars(dv)
            dv.reinit()
            return True
        else:
            return False

    @rpc(Integer, ViewParams, _returns = ViewInfo)
    @installCatchExcept
    def install_view (self, sid, params):
        dv = self.get_cache(sid,"install","vars")
        if not dv:
            dv = self.install_vars()
            langChanged = False
        else:
            langChanged = self.fixInstallLocalization(sid,dv)
            lang = dv.Get('os_install_locale_lang')
            self.set_cache(sid,"install","lang",lang,smart=False)
            dv.processRefresh()
        self.set_cache(sid, 'install', "vars",dv,smart=False)
        view = ViewInfo(dv,viewparams=params,
                        has_brief=True,
                        allsteps=langChanged,
                        brief_label=_("Start installing"))
        return view

    def install_flash_vars(self):
        dv = cl_install.DataVarsInstall()
        dv.importInstall()
        dv.flIniFile()
        dv.Set('cl_action','system',True)
        dv.Set('cl_install_type','flash')
        dv.Set('cl_dispatch_conf','usenew',True)
        dv.addGroup(_("Flash install"),
            normal=('os_install_disk_single','cl_image_filename'),
            expert=('os_location_data',),
            next_label=_("Install"))
        return dv

    @rpc(Integer, InstallInfo, _returns = Array(ReturnedMessage))
    @core_method(category=__('Installation'),title=__('Flash install'),
        image='drive-removable-media-usb-pendrive,'
              'drive-removable-media-usb,media-flash',
        gui=True, rights=['install'])
    def install_flash ( self, sid, info):
        """
        Install to flash
        """
        return self.callMethod(sid,info,logicClass=cl_install.Install,
                           method="installSystem",method_name="install_flash")

    @rpc(Integer, ViewParams,_returns = ViewInfo)
    @installCatchExcept
    def install_flash_view (self, sid, params):
        return commonView(self,sid,params,"install_flash")

    def install_pxe_vars(self):
        dv = cl_install.DataVarsInstall()
        dv.importInstall()
        dv.flIniFile()
        dv.Set('cl_action','system',True)
        dv.Set('os_install_pxe','on',True)
        dv.Set('cl_dispatch_conf','usenew',True)
        dv.addGroup(None,
            normal=('cl_image_filename',),
            expert=('os_install_pxe_path',),
            next_label=_("Install"))
        return dv

    @rpc(Integer, InstallInfo, _returns = Array(ReturnedMessage))
    @core_method(category=__('Installation'),title=__('PXE install'),
        image='network-server,preferences-desktop-remote-desktop',
        command='cl-install-pxe',
        gui=True, rights=['installpxe'])
    def install_pxe ( self, sid, info):
        """
        Install to flash
        """
        return self.callMethod(sid,info,logicClass=cl_install.Install,
                           method="installSystem",method_name="install_pxe")

    @rpc(Integer, ViewParams,_returns = ViewInfo)
    @installCatchExcept
    def install_pxe_view (self, sid, params):
        return commonView(self,sid,params,"install_pxe")

    def setup_network_vars(self):
        dv = cl_install.DataVarsInstall()
        dv.importInstall()
        dv.flIniFile()
        dv.Set('cl_action','merge',True)
        dv.Set('cl_merge_pkg',[None],True)
        dv.Set('cl_merge_set',"on",True)
        dv.Set('cl_setup','network',True)
        dv.addGroup(None,
            normal=('os_install_net_conf','os_install_net_data',
                    'os_install_net_fqdn','os_install_ntp'),
            expert=('os_install_net_dns','os_install_net_dns_search',
                    'os_install_net_route_data',
                    'cl_templates_locate',"cl_dispatch_conf","cl_verbose_set"),
            next_label=_("Save"))
        return dv

    @rpc(Integer, InstallInfo, _returns = Array(ReturnedMessage))
    @core_method(category=__('Configuration'),title=__('Network'),
        image='gnome-network-properties,'
              'network-idle,preferences-system-network',
        command="cl-setup-network",
        gui=True, rights=['setup'])
    def setup_network ( self, sid, info):
        """
        Setup network
        """
        return self.callMethod(sid,info,logicClass=cl_install.Install,
                           method="setupSystem",method_name="setup_network")

    @rpc(Integer, ViewParams,_returns = ViewInfo)
    @installCatchExcept
    def setup_network_view (self, sid, params):
        return commonView(self,sid,params,"setup_network")

    def setup_video_vars(self):
        dv = cl_install.DataVarsInstall()
        dv.importInstall()
        dv.flIniFile()
        dv.Set('cl_action','merge',True)
        dv.Set('cl_merge_pkg',[None],True)
        dv.Set('cl_merge_set',"on",True)
        dv.Set('cl_setup','video',True)
        dv.addGroup(None,
            normal=('os_install_x11_video_drv', 'os_install_x11_resolution',
                    'os_install_x11_composite', 'os_install_fb_resolution'),
            expert=('cl_templates_locate',"cl_dispatch_conf","cl_verbose_set"),
            next_label=_("Save"))
        return dv

    @rpc(Integer, InstallInfo, _returns = Array(ReturnedMessage))
    @core_method(category=__('Configuration'),title=__('Video'),
        image='video-display,gnome-multimedia',
        command="cl-setup-video",
        gui=True, rights=['setup'])
    def setup_video ( self, sid, info):
        """
        Setup video
        """
        return self.callMethod(sid,info,logicClass=cl_install.Install,
                           method="setupSystem",method_name="setup_video")

    @rpc(Integer, ViewParams,_returns = ViewInfo)
    @installCatchExcept
    def setup_video_view (self, sid, params):
        return commonView(self,sid,params,"setup_video")

    def setup_locale_vars(self):
        dv = cl_install.DataVarsInstall()
        dv.importInstall()
        dv.flIniFile()
        dv.Set('cl_action','merge',True)
        dv.Set('cl_merge_pkg',[None],True)
        dv.Set('cl_merge_set',"on",True)
        dv.Set('cl_setup','locale',True)
        dv.addGroup(None,
            normal=('os_install_locale_lang',
                    'os_install_clock_timezone'),
            expert=('cl_templates_locate',"cl_dispatch_conf","cl_verbose_set"),
            next_label=_("Save"))
        return dv

    @rpc(Integer, InstallInfo, _returns = Array(ReturnedMessage))
    @core_method(category=__('Configuration'),title=__('Locale'),
        image='locale,preferences-desktop-locale',
        command="cl-setup-locale",
        gui=True, rights=['setup'])
    def setup_locale ( self, sid, info):
        """
        Setup locale
        """
        return self.callMethod(sid,info,logicClass=cl_install.Install,
                           method="setupSystem",method_name="setup_locale")

    @rpc(Integer, ViewParams,_returns = ViewInfo)
    @installCatchExcept
    def setup_locale_view (self, sid, params):
        return commonView(self,sid,params,"setup_locale")

    def setup_boot_vars(self):
        dv = cl_install.DataVarsInstall()
        dv.importInstall()
        dv.flIniFile()
        dv.Set('cl_action','merge',True)
        dv.Set('cl_merge_pkg',[None],True)
        dv.Set('cl_merge_set',"on",True)
        dv.Set('cl_setup','boot',True)
        dv.addGroup(None,
            normal=('os_install_mbr',
                    'os_install_kernel_scheduler'),
            expert=('cl_templates_locate',"cl_dispatch_conf","cl_verbose_set"),
            next_label=_("Save"))
        return dv

    @rpc(Integer, InstallInfo, _returns = Array(ReturnedMessage))
    @core_method(category=__('Configuration'),title=__('Boot'),
        image='stock_save,drive-harddisk',command="cl-setup-boot",
        gui=True, rights=['setup'])
    def setup_boot ( self, sid, info):
        """
        Setup locale
        """
        return self.callMethod(sid,info,logicClass=cl_install.Install,
                           method="setupSystem",method_name="setup_boot")

    @rpc(Integer, ViewParams,_returns = ViewInfo)
    @installCatchExcept
    def setup_boot_view (self, sid, params):
        return commonView(self,sid,params,"setup_boot")

    def setup_system_vars(self):
        dv = cl_install.DataVarsInstall()
        dv.importInstall()
        dv.flIniFile()
        dv.Set('cl_action','merge',True)
        dv.Set('cl_live','off')
        dv.addGroup(None,
            normal=("cl_live",),
            expert=('cl_templates_locate',"cl_dispatch_conf","cl_verbose_set"),
            next_label=_("Reconfigure"))
        return dv

    @rpc(Integer, InstallInfo, _returns = Array(ReturnedMessage))
    @core_method(category=__('Configuration'),title=__('System'),
        image='system-run,system,computer',command="cl-setup-system",
        gui=True, rights=['setup'])
    def setup_system ( self, sid, info):
        """
        Setup system
        """
        return self.callMethod(sid,info,logicClass=cl_install.Install,
                           method="setupSystem",method_name="setup_system")

    @rpc(Integer, ViewParams,_returns = ViewInfo)
    @installCatchExcept
    def setup_system_view (self, sid, params):
        return commonView(self,sid,params,"setup_system")
