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

# Copyright 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 re
import sys
from calculate.lib.utils.portage import isPkgInstalled
from calculate.lib.variables.linux import LinuxDataVars
from calculate.install.distr import IsoDistributive, DistributiveError
from calculate.lib.utils.files import listDirectory
from calculate.lib.datavars import ReadonlyVariable, HumanReadable, \
    ReadonlyTableVariable, FieldValue, VariableError, Variable
from calculate.install.variables.system import VariableOsInstallX11ServerSet
from builder import (VariableClBuilderPath, VariableClBuilderKernel,
                     VariableClBuilderKernelVer, VariableClBuilderInitrdInstall,
                     VariableClBuilderVideoDriverPath,
                     VariableClBuilderVideodrvSet)
from action import Actions

_ = lambda x: x

from calculate.lib.cl_lang import setLocalTranslate

setLocalTranslate('cl_builder3', sys.modules[__name__])


class VariableClBuilderIsoLabel(ReadonlyVariable):
    """
    Метка в syslinux образе
    """
    fullname_format = "{name} {ver}{subname} {arch} {build}"

    def get(self):
        name = self.Get('os_linux_name')
        subname = self.Get('os_linux_subname')
        if subname:
            subname = " %s" % subname
        ver = self.Get('os_linux_ver')
        build = self.Get('os_linux_build')
        arch = self.Get('os_arch_machine')
        return self.fullname_format.format(
            name=name, ver=ver, subname=subname, arch=arch, build=build)


class VariableClBuilderSplash(ReadonlyVariable):
    """
    Тип splash в образе
    """

    def get(self):
        prefix = self.Get('cl_builder_path')
        if isPkgInstalled('media-gfx/splashutils', prefix=prefix):
            return "splashutils"
        elif isPkgInstalled("media-gfx/plymouth-themes-calculate",
                            prefix=prefix):
            return "plymouth"
        else:
            return ""


class DataVarsBuilderImage(LinuxDataVars):
    def variables(self):
        l = super(DataVarsBuilderImage, self).variables()
        return l + [
            VariableClBuilderPath(),
            VariableClBuilderKernel(),
            VariableClBuilderInitrdInstall(),
            VariableClBuilderKernelVer(),
            VariableOsInstallX11ServerSet(image=False,
                                          prefix_variable="cl_builder_path"),
            VariableClBuilderVideoDriverPath(),
            VariableClBuilderVideodrvSet(autodetect=True),
            VariableClBuilderIsoLabel(),
            VariableClBuilderSplash(),
        ]

    def init_variables(self):
        self['cl_builder_path'] = self.systemRoot
        return True


class VariableClBuilderImageBootparam(Variable):
    """
    Стандартная строка загрзки live образа
    """


class VariableClBuilderImageData(ReadonlyTableVariable):
    """
    Информация о прочих репозиториях
    """
    source = ['cl_builder_image_id',
              'cl_builder_image_label',
              'cl_builder_image_iso',
              'cl_builder_image_vmlinuz_orig',
              'cl_builder_image_vmlinuz',
              'cl_builder_image_initrd_orig',
              'cl_builder_image_initrd',
              'cl_builder_image_xorg',
              'cl_builder_image_drivers',
              'cl_builder_image_splash',
              ]

    def generate_name(self, basename, namelist):
        if basename not in namelist:
            return basename
        for n in range(1, 99):
            newname = "%s-%d" % (basename, n)
            if newname not in namelist:
                return newname
        raise VariableError(_("Failed to generate kernel name"))

    parser = re.compile(r"^.*/(.*?)-(\d+)(-\d+)?-(x86_64|i686)\.iso$")

    def sortkey(self, x):
        m = self.parser.search(x)
        if m:
            return (m.group(1), m.group(2),
                    -int(m.group(3)) if m.group(3) else 0, m.group(4))
        else:
            return x,

    def generator(self, isopath):
        n = 1
        numbered = re.compile(r"^.*-(\d{1,3})-(?:x86_64|i686)\.iso$")
        for iso_image in sorted(
                [x for x in listDirectory(isopath, fullPath=True)
                 if x.endswith('.iso')],
                key=self.sortkey):
            try:
                with IsoDistributive(iso_image) as image:
                    dn = image.getDirectory()
                    dv = DataVarsBuilderImage(dn)

                    kernel = dv['cl_builder_kernel']
                    kernel_copy = "vmlinuz-%d" % n
                    initrd = dv['cl_builder_initrd_install']
                    initrd_copy = "initrd-%d" % n

                    label = dv['cl_builder_iso_label']
                    m = numbered.search(iso_image)
                    if m:
                        label = "%s-%s" % (label, m.group(1))

                    yield ["cl-%d" % n,
                           label,
                           iso_image,
                           kernel, kernel_copy,
                           initrd, initrd_copy,
                           dv['os_install_x11_server_set'],
                           dv['cl_builder_videodrv_set'],
                           dv['cl_builder_splash'],
                           ]
                    n += 1
            except DistributiveError:
                pass

    def get(self, hr=HumanReadable.No):
        isopath = self.Get('cl_builder_flash_repository')
        if self.Get('cl_builder_action') != Actions.ImageMenu or not isopath:
            return [[]]
        return list(self.generator(isopath))


class VariableClBuilderImageId(FieldValue, ReadonlyVariable):
    """
    Идентификаторы образов
    """
    type = "list"
    source_variable = "cl_builder_image_data"
    column = 0


class VariableClBuilderImageLabel(FieldValue, ReadonlyVariable):
    """
    Идентификаторы образов
    """
    type = "list"
    source_variable = "cl_builder_image_data"
    column = 1


class VariableClBuilderImageIso(FieldValue, ReadonlyVariable):
    """
    Пути до iso образов
    """
    type = "list"
    source_variable = "cl_builder_image_data"
    column = 2


class VariableClBuilderImageVmlinuzOrig(FieldValue, ReadonlyVariable):
    """
    Пути до vmlinuz
    """
    type = "list"
    source_variable = "cl_builder_image_data"
    column = 3


class VariableClBuilderImageVmlinuz(FieldValue, ReadonlyVariable):
    """
    Пути до vmlinuz
    """
    type = "list"
    source_variable = "cl_builder_image_data"
    column = 4


class VariableClBuilderImageInitrdOrig(FieldValue, ReadonlyVariable):
    """
    Пути до initrd
    """
    type = "list-bool"
    source_variable = "cl_builder_image_data"
    column = 5


class VariableClBuilderImageInitrd(FieldValue, ReadonlyVariable):
    """
    Пути до initrd
    """
    type = "list-bool"
    source_variable = "cl_builder_image_data"
    column = 6


class VariableClBuilderImageXorg(FieldValue, ReadonlyVariable):
    """
    Содержит ли образ xorg-server
    """
    type = "list-bool"
    source_variable = "cl_builder_image_data"
    column = 7


class VariableClBuilderImageDrivers(FieldValue, ReadonlyVariable):
    """
    Содержит ли образ проприетарные видеодраверы
    """
    type = "list"
    source_variable = "cl_builder_image_data"
    column = 8


class VariableClBuilderImageSplash(FieldValue, ReadonlyVariable):
    """
    Какой сплэш содержит образ
    """
    type = "list"
    source_variable = "cl_builder_image_data"
    column = 9
