# -*- coding: utf-8 -*-
#
# This file is part of Karesansui.
#
# Copyright (C) 2009 HDE, Inc.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#

import web
from web.utils import Storage

import karesansui
from karesansui.lib.rest import Rest, auth

from karesansui.lib.utils import \
    comma_split, uniq_sort, is_param, json_dumps

from karesansui.lib.checker import Checker, \
    CHECK_EMPTY, CHECK_LENGTH, CHECK_ONLYSPACE

from karesansui.lib.const import \
    NOTE_TITLE_MIN_LENGTH, NOTE_TITLE_MAX_LENGTH, \
    MACHINE_NAME_MIN_LENGTH, MACHINE_NAME_MAX_LENGTH, \
    TAG_MIN_LENGTH, TAG_MAX_LENGTH, \
    VIRT_COMMAND_DELETE_GUEST

from karesansui.lib.virt.virt import KaresansuiVirtConnection
from karesansui.lib.merge import MergeGuest

from karesansui.db.access.machine import \
     findbyguest1, findby1name, logical_delete, \
     update as m_update, delete as m_delete

from karesansui.db.access.machine2jobgroup import new as m2j_new
from karesansui.db.access._2pysilhouette import save_job_collaboration
from karesansui.db.access.tag import \
     new as t_new, samecount as t_count, findby1name as t_name

from karesansui.db.model.machine import HYPERVISOR

from karesansui.db.model._2pysilhouette import Job, JobGroup
from pysilhouette.command import dict2command

def validates_guest_edit(obj):
    checker = Checker()
    check = True

    _ = obj._
    checker.errors = []

    if not is_param(obj.input, 'm_name'):
        check = False
        checker.add_error(_('Parameter m_name does not exist.'))
    else:
        check = checker.check_string(
                    _('Machine Name'),
                    obj.input.m_name,
                    CHECK_EMPTY | CHECK_LENGTH | CHECK_ONLYSPACE,
                    None,
                    min = MACHINE_NAME_MIN_LENGTH,
                    max = MACHINE_NAME_MAX_LENGTH,
            ) and check

    if is_param(obj.input, 'note_title'):
        check = checker.check_string(
                    _('Title'),
                    obj.input.note_title,
                    CHECK_LENGTH | CHECK_ONLYSPACE,
                    None,
                    min = NOTE_TITLE_MIN_LENGTH,
                    max = NOTE_TITLE_MAX_LENGTH,
                ) and check

    if is_param(obj.input, 'note_value'):
        check = checker.check_string(
                    _('Note'),
                    obj.input.note_value,
                    CHECK_ONLYSPACE,
                    None,
                    None,
                    None,
                ) and check


    if is_param(obj.input, 'tags'):
        for tag in comma_split(obj.input.tags):
            check = checker.check_string(
                        _('Tag'),
                        tag,
                        CHECK_LENGTH | CHECK_ONLYSPACE,
                        None,
                        min = TAG_MIN_LENGTH,
                        max = TAG_MAX_LENGTH,
                    ) and check

    obj.view.alert = checker.errors
    return check

class GuestBy1(Rest):

    def _post(self, f):
        ret = Rest._post(self, f)
        if hasattr(self, "kvc") is True:
            self.kvc.close()
        return ret

    @auth
    def _GET(self, *param, **params):
        (host_id, guest_id) = self.chk_guestby1(param)
        if guest_id is None:
            web.notfound()
        model = findbyguest1(self.orm, guest_id)

        self.kvc = KaresansuiVirtConnection()
        if self.is_mode_input() is True:
            try:
                domname = self.kvc.uuid_to_domname(model.uniq_key)
                #if not domname: return web.conflict(web.ctx.path)
                virt = self.kvc.search_kvg_guests(domname)[0]
                guest = MergeGuest(model, virt)
                self.view.model = guest.info["model"]
                
            except:
                self.kvc.close()
                raise
            
            return True

        else:
            try:
                domname = self.kvc.uuid_to_domname(model.uniq_key)
                #if not domname: return web.conflict(web.ctx.path)
                virt = self.kvc.search_kvg_guests(domname)[0]

                guest = MergeGuest(model, virt)

                guest_info = guest.info["virt"].get_info()
                info = {}
                info['memory'] = guest_info["memory"]
                info['cpu'] = guest_info["cpuTime"]
                info['os'] = guest_info["OSType"]

                guest_diskinfo = guest.info["virt"].get_disk_info()
                disks = []
                for disk in guest_diskinfo:
                    disks.append("%s(%sMB)" % (disk['target']['dev'],disk['source']['size']))
                diskinfo = disks

                guest_interfaceinfo = guest.info["virt"].get_interface_info()
                inters = []
                for inter in guest_interfaceinfo:
                    inters.append(inter["type"])
                interfaceinfo = inters

                guest_netinfo = guest.info["virt"].get_netinfo()
                nics = []
                for nic in guest_netinfo.keys():
                    nics.append(nic)
                netinfo = nics

                if self.__template__["media"] == 'json':
                    json_guest = guest.get_json(self.me.languages)
                    self.view.data = json_dumps(
                        {
                            "model": json_guest["model"],
                            "virt": json_guest["virt"],
                            "autostart": guest.info["virt"].autostart(),
                            "info": info,
                            "diskinfo": diskinfo,
                            "netinfo": netinfo,
                            "interfaceinfo": interfaceinfo
                        }
                    )
                else:
                    self.view.model = guest.info["model"]
                    self.view.virt = guest.info["virt"]
                    self.view.autostart = guest.info["virt"].autostart()
                    self.view.info = info
                    self.view.diskinfo = diskinfo
                    self.view.netinfo = netinfo
                    self.view.interfaceinfo = interfaceinfo
            except:
                self.kvc.close()
                raise
            
            return True

    @auth
    def _PUT(self, *param, **params):

        (host_id, guest_id) = self.chk_guestby1(param)
        if guest_id is None: web.notfound()

        if not validates_guest_edit(self):
            self.logger.debug("Update Guest OS is failed, Invalid input value.")
            return web.badrequest(self.view.alert)

        guest = findbyguest1(self.orm, guest_id)

        # notebook
        if is_param(self.input, "note_title"):
            guest.notebook.title = self.input.note_title
        if is_param(self.input, "note_value"):
            guest.notebook.value = self.input.note_value

        if is_param(self.input, "m_name"):
            guest.name = self.input.m_name
    
        # Icon
        icon_filename = None
        if is_param(self.input, "icon_filename", empty=True):
            guest.icon = self.input.icon_filename

        # tag UPDATE
        if is_param(self.input, "tags"):
            _tags = []
            tag_array = comma_split(self.input.tags)
            tag_array = uniq_sort(tag_array)
            for x in tag_array:
                if t_count(self.orm, x) == 0:
                    _tags.append(t_new(x))
                else:
                    _tags.append(t_name(self.orm, x))
            guest.tags = _tags

        guest.modified_user = self.me

        m_update(self.orm, guest)
        return web.seeother(web.ctx.path)


    @auth
    def _DELETE(self, *param, **params):

        (host_id, guest_id) = self.chk_guestby1(param)
        if guest_id is None: web.notfound()

        guest = findbyguest1(self.orm, guest_id)

        self.kvc = KaresansuiVirtConnection()
        try:
            domname = self.kvc.uuid_to_domname(guest.uniq_key)
            #if not domname: return web.conflict(web.ctx.path)
            if not domname:
                self.logger.info("Did not exist in libvirt. - guestid=%s" % guest_id)
                logical_delete(self.orm, guest)
                self.orm.commit()
                return web.nocontent()
        except:
            self.kvc.close()
            raise
            
        action_cmd = dict2command(
            "%s/%s" % (karesansui.config['application.bin.dir'], VIRT_COMMAND_DELETE_GUEST),
            {"name" : domname})

        cmdname = "Delete Guest"  
        _jobgroup = JobGroup(cmdname, karesansui.sheconf['env.uniqkey'])
        _job = Job('%s command' % cmdname, 0, action_cmd)
        _jobgroup.jobs.append(_job)
        

        logical_delete(self.orm, guest)

        _machine2jobgroup = m2j_new(machine=guest,
                       jobgroup_id=-1,
                       uniq_key=karesansui.sheconf['env.uniqkey'],
                       created_user=self.me,
                       modified_user=self.me,
                       )

        save_job_collaboration(self.orm,
                               self.pysilhouette.orm,
                               _machine2jobgroup,
                               _jobgroup,
                               )
        
        return web.accepted(url = web.ctx.path)  

urls = (
    '/host/(\d+)/guest/(\d+)/?(\.html|\.part|\.json)?$', GuestBy1,
    )
