# -*- 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 os

import web

import karesansui
from karesansui.lib.rest import Rest, auth
from karesansui.lib.const import VIRT_SNAPSHOT_DIR, \
     VIRT_COMMAND_DELETE_SNAPSHOT, \
     ID_MIN_LENGTH, ID_MAX_LENGTH, \
     NOTE_TITLE_MIN_LENGTH, NOTE_TITLE_MAX_LENGTH

from karesansui.lib.utils import getfilesize_str, is_param, get_filesize_MB, json_dumps
from karesansui.lib.virt.virt import KaresansuiVirtConnection

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

from karesansui.db.access.snapshot import findby1, logical_delete
from karesansui.db.access._2pysilhouette import save_job_collaboration
from karesansui.db.access.machine2jobgroup import new as m2j_new

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

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

    _ = obj._
    checker.errors = []

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

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

    obj.view.alert = checker.errors

    return check
    
def validates_param_id(obj, snapshot_id):
    checker = Checker()
    check = True

    _ = obj._
    checker.errors = []

    check = checker.check_number(
            _('Snapshot ID'),
            snapshot_id,
            CHECK_EMPTY | CHECK_VALID | CHECK_MIN | CHECK_MAX,
            min = ID_MIN_LENGTH,
            max = ID_MAX_LENGTH,
        ) and check
    
    obj.view.alert = checker.errors

    return check

class GuestBy1SnapshotBy1(Rest):

    @auth
    def _GET(self, *param, **params):
        (host_id, guest_id) = self.chk_guestby1(param)
        if guest_id is None: return web.notfound()
        
        snapshot_id = param[2]        
        if not validates_param_id(self, snapshot_id):
            return web.notfound(self.view.alert)

        snapshot = findby1(self.orm, snapshot_id)
        if not snapshot:
            return web.notfound()
        
        kvc = KaresansuiVirtConnection()
        try:
            domname = kvc.uuid_to_domname(snapshot.machine.uniq_key)
            if not domname: return web.conflict(web.ctx.path)
        finally:
            kvc.close()
            
        filepath = "%s/%s/%s" % (VIRT_SNAPSHOT_DIR, domname, snapshot.name)
        if os.path.isfile(filepath) is False:
            self.logger.error("The specified snapshot file does not exist. - %s" % filepath)
            return False

        if self.__template__["media"] == 'json':
            self.view.snapshot = json_dumps((
                snapshot.get_json(self.me.languages),
                get_filesize_MB(getfilesize_str(filepath)),
                VIRT_SNAPSHOT_DIR
                ))
        else:
            self.view.snapshot = (snapshot,
                                  domname,
                                  get_filesize_MB(getfilesize_str(filepath)),
                                  VIRT_SNAPSHOT_DIR,
                                  filepath)
        return True

    @auth
    def _PUT(self, *param, **params):
        (host_id, guest_id) = self.chk_guestby1(param)
        if guest_id is None: return web.notfound()

        snapshot_id = param[2]
        if not validates_param_id(self, snapshot_id):
            return web.notfound(self.view.alert)

        if not validates_snapshot(self):
            return web.badrequest(self.view.alert)

        snapshot = findby1(self.orm, snapshot_id)
        if not snapshot:
            return web.notfound()

        snapshot.notebook.title = self.input.title
        snapshot.notebook.value = self.input.value

        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: return web.notfound()

        snapshot_id = param[2]
        if not validates_param_id(self, snapshot_id):
            return web.notfound(self.view.alert)

        snapshot = findby1(self.orm, snapshot_id)
        if not snapshot:
            return web.notfound()

        kvc = KaresansuiVirtConnection()
        try:
            domname = kvc.uuid_to_domname(snapshot.machine.uniq_key)
            if not domname: return web.conflict(web.ctx.path)
        finally:
            kvc.close()

        # delete
        action_cmd = dict2command(
            "%s/%s" % (karesansui.config['application.bin.dir'],
                       VIRT_COMMAND_DELETE_SNAPSHOT),
            {"name" : domname, "id" : snapshot.name})

        cmdname = 'Delete Snapshot'
        _jobgroup = JobGroup(cmdname, karesansui.sheconf['env.uniqkey'])
        _job = Job('%s command' % cmdname, 0, action_cmd)
        _jobgroup.jobs.append(_job)
        
        _machine2jobgroup = m2j_new(machine=snapshot.machine,
                                    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,
                               )        
        logical_delete(self.orm, snapshot)
        return web.accepted()

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