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

# Copyright 2011-2013 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.

from calculate.lib.datavars import Variable,ReadonlyVariable,VariableError
import sys, re,os
from os import path

from calculate.lib.cl_lang import setLocalTranslate
from calculate.core.server.decorators import Dec
import pwd
#from calculate.api.cert_cmd import find_id_cert
setLocalTranslate('cl_core3',sys.modules[__name__])

from calculate.lib.utils.files import listDirectory
from calculate.lib.utils.portage import isPkgInstalled,reVerSplitToPV, \
                                        getPkgSlot
from calculate.lib.utils.common import getTupleVersion
from calculate.lib.variables.user import VariableUrLogin
from itertools import *
import glob

class VariableClCorePkgName(Variable):
    """
    Package name
    """
    type = "choiceedit"
    opt = ["--pkg-name"]
    metavalue = "PN"
    untrusted = True

    def init(self):
        self.label = _("Package name")
        self.help = _("package name")

    def check(self,value):
        if not value: 
            raise VariableError(_("Please choose a package"))
        if not os.environ.get("EBUILD_PHASE","") and not value in self.choice():
            raise VariableError(_("Package not found"))

    def choice(self):
        if self.Get('cl_ebuild_phase'):
            return [""]
        return [""]+["all"]+\
            sorted(set(chain(*map(lambda x:map(lambda y:y[0].rpartition('-')[0] if y[2].startswith('r') else y[0],
            imap(lambda y:y.rpartition('-'),
            listDirectory(x))),
            listDirectory('/var/db/pkg',onlyDir=True,fullPath=True)))))

class VariableClCorePkgVersion(Variable):
    """
    Package version
    """
    type = "choiceedit"
    opt = ["--pkg-version"]
    metavalue = "PVR"
    untrusted = True

    def init(self):
        self.label = _("Package version")
        self.help = _("package version number with the revision")

    def get(self):
        pkg = isPkgInstalled("%s/%s"%(self.Get('cl_core_pkg_category'),
                                      self.Get('cl_core_pkg_name')))
        if pkg:
            return sorted(pkg,
                   key=lambda x:getTupleVersion(x['PVR']))[-1]['PVR']
        return ""

    def check(self,value):
        pkg_name = self.Get('cl_core_pkg_name')
        if not value and pkg_name and pkg_name != "all":
            raise VariableError(_("Please choose the version"))

class VariableClCorePkgSlot(Variable):
    """
    Package version
    """
    type = "choiceedit"
    opt = ["--pkg-slot"]
    metavalue = "SLOT"
    untrusted = True

    def init(self):
        self.label = _("Package slot")
        self.help = _("package slot")

    def get(self):
        pkg = getPkgSlot("%s/%s"%(self.Get('cl_core_pkg_category'),
                                      self.Get('cl_core_pkg_name')))
        if pkg:
            return sorted(pkg)[-1]
        return ""

    def check(self,value):
        pkg_name = self.Get('cl_core_pkg_name')
        if not value and pkg_name and pkg_name != "all":
            raise VariableError(_("Please choose the slot"))

class VariableClCorePkgCategory(Variable):
    """
    Package category
    """
    type = "choiceedit"
    opt = ["--pkg-category"]
    metavalue = "CATEGORY"
    untrusted = True
    pkgCategories = {}


    def init(self):
        self.label = _("Package category")
        self.help = _("package category name")

    def choice(self):
        if self.Get('cl_ebuild_phase'):
            return []
        pkgName = self.Get('cl_core_pkg_name')
        if not pkgName in self.pkgCategories:
            self.pkgCategories[pkgName] = \
                glob.glob('/usr/portage/*/%s'%pkgName)
        return map(lambda x:path.split(path.split(x)[0])[1],
               self.pkgCategories[pkgName])

    def get(self):
        category = isPkgInstalled(self.Get('cl_core_pkg_name'))
        if category:
            if type(category[0]) == dict:
                category = ""
            else:
                category = category[0].rpartition('/')[2]
        else:
            choice = self.choice()
            if len(choice) == 1:
                return choice[0]
            else:
                category = ""
        return category

    def check(self,value):
        pkg_name = self.Get('cl_core_pkg_name')
        if not value and pkg_name and pkg_name != "all":
            raise VariableError(_("Please choose the category"))

class VariableClCorePkgPath(Variable):
    """
    Package configure path
    """

    value = "/"
    opt = ["--pkg-path"]
    metavalue = "PATH"

    def init(self):
        self.label = _("Path for configuration")
        self.help = _("root path for saving the updated configuration files")

    def check(self,value):
        if not path.isdir(value):
            raise VariableError(_("Directory %s not found")%value)

class VariableClCorePkgSystemSet(Variable):
    """
    Package configure system
    """

    type = "bool"
    value = "on"
    opt = ["--system"]
    metavalue = "ON/OFF"

    def init(self):
        self.label = _("Configure the system")
        self.help = _("updating system configuration files")

class VariableClCorePkgDesktopSet(Variable):
    """
    Package configure desktop
    """

    type = "bool"
    opt = ["--desktop"]
    metavalue = "ON/OFF"

    def get(self):
        if self.Get('cl_templates_locate') == ["clt"]:
            return "off"
        return "on"

    def check(self,value):
        if self.Get('cl_templates_locate') == ["clt"] and value == "on":
            raise VariableError(
                _("You shouldn't choice only clt location "
                  "for desktop templates"))

    def init(self):
        self.label = _("Configure users")
        self.help = _("updating desktop (user) configuration files")

class VariableClCorePkgRootSet(Variable):
    """
    Other packages (specified by merge=) will configured in /
    """
    type = "bool"
    value = "on"
    metavalue = "ON/OFF"

    opt = ["--depend-in-root"]

    def init(self):
        self.label = _("Configure dependent packages in root")
        self.help = _("configure the dependent packages in the same directory as the specified package, instead of root")

class VariableUrCoreLogin(VariableUrLogin):
    """
    User Login
    """
    opt = ["--login"]
    alias = "ur_login"

    def check(self,value):
        """Пользователь существует"""
        try:
            pwd.getpwnam(value).pw_gid
        except:
            raise VariableError(_("User %s does not exist")%value)

    def get(self):
        return self.Get('ur_login')
