# Copyright 2015-2017 F-Secure

# 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 time
from threading import Lock
import xml.etree.ElementTree as etree

import libvirt

from see.interfaces import Context
from see.environment import load_configuration

NOSTATE = 0
RUNNING = 1
BLOCKED = 2
PAUSED = 3
SHUTDOWN = 4
SHUTOFF = 5
CRASHED = 6
SUSPENDED = 7

STATES_MAP = {NOSTATE: (),
              RUNNING: ('pause',
                        'poweroff',
                        'forced_poweroff',
                        'restart',
                        'shutdown'),
              BLOCKED: (),
              PAUSED: ('resume',
                       'forced_poweroff'),
              SHUTDOWN: ('poweron'),
              SHUTOFF: ('poweron'),
              CRASHED: ('poweron'),
              SUSPENDED: ('resume')}


class QEMUContextFactory(object):
    """Builds a SeeContext object based on QEMUResources."""
    def __init__(self, configuration):
        self.configuration = load_configuration(configuration)

    def __call__(self, identifier):
        from see.context.resources.qemu import QEMUResources

        resources = QEMUResources(identifier, self.configuration)

        try:
            resources.allocate()
        except Exception:
            resources.deallocate()
            raise

        return SeeContext(identifier, resources)


class LXCContextFactory(object):
    """Builds a SeeContext object based on LXCResources."""
    def __init__(self, configuration):
        self.configuration = load_configuration(configuration)

    def __call__(self, identifier):
        from see.context.resources.lxc import LXCResources

        resources = LXCResources(identifier, self.configuration)

        try:
            resources.allocate()
        except Exception:
            resources.deallocate()
            raise

        return SeeContext(identifier, resources)


class VBoxContextFactory(object):
    """Builds a SeeContext object based on VBoxResources."""
    def __init__(self, configuration):
        self.configuration = load_configuration(configuration)

    def __call__(self, identifier):
        from see.context.resources.vbox import VBoxResources

        resources = VBoxResources(identifier, self.configuration)

        try:
            resources.allocate()
        except Exception:
            resources.deallocate()
            raise

        return SeeContext(identifier, resources)


class SeeContext(Context):
    """