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

# Copyright 2011-2015 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 sys
import re
from calculate.core.server.core_interfaces import MethodsInterface

from calculate.lib.cl_lang import setLocalTranslate, getLazyLocalTranslate

_ = lambda x: x
setLocalTranslate('cl_core3', sys.modules[__name__])
__ = getLazyLocalTranslate(_)

VARIABLE, MODE, LOCATION, VALUE = 0, 1, 2, 3


class Variables(MethodsInterface):
    def writeVariables(self, vardata):
        """
        Write variable to env files, or delete from env files
        """
        dv = self.clVars
        data = filter(lambda x: x[LOCATION] or
                                not x[LOCATION] and
                                dv.isFromIni(x[VARIABLE].rpartition('.')[2]),
                      vardata)
        if data:
            head = [_("Variable"), _("Mode"), _("Location"), _("Value")]
            self.printTable(_("List of variables"), head, data)
            for varname, mode, location, value in data:
                if location:
                    value = dv.unserialize(dv.getInfo(varname).type, str(value))
                section, op, varname = varname.rpartition('.')
                if not location:
                    for env_location in dv.Get('main.cl_env_location'):
                        if not dv.Delete(varname, location, header=section):
                            self.printWARNING(
                                _("Failed to delete variable {var} from "
                                  "{location}").format(
                                    var=varname, location=env_location))
                else:
                    if varname in dv.iniCache:
                        oldValue = dv.unserialize(
                            dv.getInfo(varname).type,
                            str(dv.iniCache[varname]['value']))
                    else:
                        oldValue = None
                    if value != oldValue:
                        dv.Write(varname, value, location=location,
                                 header=section)
        else:
            self.printSUCCESS("Nothing to set")
        return True

    def showVariables(self, showVal, filterVal, vardata):
        """
        Show variables by cl_variable_filter
        """
        dv = self.clVars
        removeQuotes = lambda x: x if x != "''" else ""
        reIndex = re.compile("((?:\w+\.)?(\w+))(?:\[(\d+)\])")
        if showVal:
            index = reIndex.search(showVal)
            if index:
                varname = index.group(1)
                index = int(index.group(3))
            else:
                varname = showVal
            prevVal = str(dv.Select('cl_variable_value',
                                    where='cl_variable_fullname',
                                    eq=varname, limit=1))
            if index is not None:
                typeVar = dv.getInfo(varname).type
                val = dv.unserialize(typeVar, prevVal)
                if index < len(val):
                    self.printDefault(removeQuotes(val[index]))
                else:
                    self.printDefault("")
            else:
                self.printDefault(removeQuotes(prevVal))
            return True
        filter_names = {'all': None,
                        'userset': lambda x: x[LOCATION],
                        'writable': lambda x: x[MODE].startswith("w"),
                        'system': lambda x: x[LOCATION] == "system",
                        'local': lambda x: x[LOCATION] == "local",
                        'remote': lambda x: x[LOCATION] == "remote"}
        filterFunc = filter_names.get(filterVal,
                                      lambda x: filterVal in x[VARIABLE])
        body = filter(filterFunc, vardata)
        dv.close()
        if body:
            head = [_("Variable"), _("Mode"),
                    _("Location"), _("Value")]
            self.printTable(_("List of variables"), head, body)
            return True
        else:
            self.printWARNING(_("No such variables"))
        return True
