# Copyright 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, ClassSerializer
from soaplib.service import rpc, DefinitionBase
from calculate.core.server.api_types import ReturnedMessage
from calculate.core.server.api_types import ChoiceValue, Table, Option, Field, \
                                           GroupField, ViewInfo, ViewParams
from calculate.lib.datavars import VariableError,DataVarsError
from calculate.client.cl_client import ClientError

from cl_client import Client,DataVarsClient
import cl_client
from calculate.lib.cl_lang import setLocalTranslate,getLazyLocalTranslate
from calculate.core.server.decorators import Dec
from calculate.core.server.func import catchExcept
core_method = Dec.core_method
setLocalTranslate('cl_client3',sys.modules[__name__])
import traceback
from functools import wraps,WRAPPER_ASSIGNMENTS

__ = getLazyLocalTranslate(_)

class ClientInfo(ClassSerializer):
    """Parameters for method install"""
    cl_localhost_set = Boolean
    cl_remote_host_new = String
    cl_remote_pw = String
    cl_client_mount_set = Boolean

    Default = Array(String)
    CheckOnly = Boolean
    CheckAll = Boolean

class ClientPasswdInfo(ClassSerializer):
    """Parameters for method install"""
    ur_login = String
    ur_user_pw = String
    ur_user_new_pw = String

    Default = Array(String)
    CheckOnly = Boolean
    CheckAll = Boolean

class SyncInfo(ClassSerializer):
    """Parameters for method install"""
    ur_login = String
    cl_client_sync = Boolean

    Default = Array(String)
    CheckOnly = Boolean
    CheckAll = Boolean


clientCatchExcept = catchExcept(VariableError,DataVarsError,
                                ClientError)

class Wsdl:
    """
    cl-client
    """
    @rpc(Integer, ClientInfo, _returns = Array(ReturnedMessage))
    @core_method(category=__('Client'),title=__('Domain'),
        image='network-workgroup',
        gui=True,command='cl-client',
        rights=['domain'])
    def client(self, sid, info):
        return self.callMethod(sid,info,method_name="client",
                               logicClass=Client,
                               method="domain")

    def client_vars(self,dv=None):
        if not dv:
            dv = DataVarsClient()
            dv.importClient()
            dv.flIniFile()
            dv.Set('cl_action','domain',True)
        dv.addGroup(None,
            normal=('cl_localhost_set','cl_remote_host_new',
                    'cl_remote_pw'),
            expert=('cl_client_mount_set',),
            next_label=_("Configure"))
        return dv

    @rpc(Integer, ViewParams,_returns = ViewInfo)
    def client_view (self, sid, params):
        dv = self.get_cache(sid,"client","vars")
        if not dv:
            dv = self.client_vars()
            if hasattr(params,"clienttype") and params.clienttype == "gui":
                try:
                    if dv.Get('cl_remote_host') == '':
                        dv.Set('cl_localhost_set',"on")
                    else:
                        dv.Set('cl_localhost_set',"off")
                except VariableError as e:
                    pass
        else:
            dv.processRefresh()
        view = ViewInfo(dv,viewparams=params)
        self.set_cache(sid, 'client', "vars",dv,smart=False)
        return view

    """
    cl-client-sync-login
    """
    @rpc(Integer, SyncInfo, _returns = Array(ReturnedMessage))
    @core_method(category=__('Client'),title=__('Domain user login'),
        image='applications-other',
        gui=False,command='cl-client-sync-login',
        rights=['domainuser'])
    def client_sync_login(self, sid, info):
        return self.callMethod(sid,info,method_name="client_sync_login",
                               logicClass=Client,
                               method="mountUserResAndSync")

    def client_sync_login_vars(self,dv=None):
        if not dv:
            dv = DataVarsClient()
            dv.importClient()
            dv.flIniFile()
            dv.Set('cl_action','login',True)
        dv.addGroup(None,
            normal=('ur_login','cl_client_sync'),
            next_label=_("Configure"))
        return dv

    @rpc(Integer, ViewParams,_returns = ViewInfo)
    def client_sync_login_view (self, sid, params):
        dv = self.get_cache(sid,"client_sync_login","vars")
        if not dv:
            dv = self.client_sync_login_vars()
        else:
            dv.processRefresh()
        view = ViewInfo(dv,viewparams=params)
        self.set_cache(sid, 'client_sync_login', "vars",dv,smart=False)
        return view

    """
    cl-client-sync-logout
    """
    @rpc(Integer, SyncInfo, _returns = Array(ReturnedMessage))
    @core_method(category=__('Client'),title=__('Domain user logout'),
        image='applications-other',
        gui=False,command='cl-client-sync-logout',
        rights=['domainuser'])
    def client_sync_logout(self, sid, info):
        return self.callMethod(sid,info,method_name="client_sync_logout",
                               logicClass=Client,
                               method="umountUserResAndSync")

    def client_sync_logout_vars(self,dv=None):
        if not dv:
            dv = DataVarsClient()
            dv.importClient()
            dv.flIniFile()
            dv.Set('cl_action','logout',True)
        dv.addGroup(None,
            normal=('ur_login','cl_client_sync'),
            next_label=_("Configure"))
        return dv

    @rpc(Integer, ViewParams,_returns = ViewInfo)
    def client_sync_logout_view (self, sid, params):
        dv = self.get_cache(sid,"client_sync_logout","vars")
        if not dv:
            dv = self.client_sync_logout_vars()
        else:
            dv.processRefresh()
        view = ViewInfo(dv,viewparams=params)
        self.set_cache(sid, 'client_sync_logout', "vars",dv,smart=False)
        return view

    """
    cl-passwd
    """
    @rpc(Integer, ClientPasswdInfo, _returns = Array(ReturnedMessage))
    @core_method(category=__('Client'),title=__('Change password'),
        image='system-users',
        gui=True,command='cl-passwd',
        rights=['password'],user=True)
    def clientpasswd(self, sid, info):
        return self.callMethod(sid,info,method_name="clientpasswd",
                               logicClass=Client,
                               method="clientPasswd")

    def clientpasswd_vars(self,dv=None):
        if not dv:
            dv = DataVarsClient()
            dv.importClient()
            dv.flIniFile()
            dv.Set('cl_action','passwd',True)
        dv.addGroup(None,
            normal=('ur_login','ur_user_pw','ur_user_new_pw'),
            next_label=_("Change password"))
        return dv

    @rpc(Integer, ViewParams,_returns = ViewInfo)
    def clientpasswd_view (self, sid, params):
        dv = self.get_cache(sid,"clientpasswd","vars")
        if not dv:
            dv = self.clientpasswd_vars()
        else:
            dv.processRefresh()
        view = ViewInfo(dv,viewparams=params)
        self.set_cache(sid, 'clientpasswd', "vars",dv,smart=False)
        return view
