# coding: utf-8
# flake8: noqa

import os
from os import path
import subprocess
import yaml

import vagrant
import nepho
from nepho.core.common import cwd
#from nepho.core import common, resource
#from nepho.core import  provider
#import nepho.core.provider

NEPHO_VAGRANT_BOILER_PLATE = """#
# Autogenerated by nepho's vagrant provider.
#
# Any changes here will be overwritten.
#
"""


class VagrantProvider(nepho.core.provider.AbstractProvider):
    """An infrastructure provider class for Vagrant"""

    PROVIDER_ID = "vagrant"
    TEMPLATE_FILENAME = "Vagrantfile"

    def __init__(self, config, scenario=None):
        nepho.core.provider.AbstractProvider.__init__(self, config, scenario)
        self.params = {
            'VagrantBackend': 'virtualbox'
        }

    @property
    def vagrantfile_path(self):
        # Lazy-load path because it requires a valid context.
        return os.path.join(
            self.scenario.context['cloudlet']['path'], 'resources',
            self.scenario.context['blueprint']['name'])

    @property
    def vagrant_backend(self):
        context = self.scenario.context
        if context['parameters']['VagrantBackend'] is None:
            print colored("Error: ", "red"), "Vagrant requires a valid backend provider, such as 'virtualbox'."
            print "Use \"nepho parameter set VagrantBackend <value>\" to set a parameter."
            exit(1)
        return context['parameters']['VagrantBackend']

    def validate_template(self, template_str):
        return "Validation:\n  Vagrant does not support validation."

    def deploy(self, debug=False):
        # FIXME: For the moment, we are just using the Vagrantfile inside the
        # cloudlet.  We should move the template-processed Vagrantfile into a
        # working directory along with the payload, then run it from there.

        with cwd(self.vagrantfile_path):
            v = vagrant.Vagrant()
            vm_name = None
            try:
                print 'Nepho Elves are now building your Stack.... this may take a couple of minutes.'
                v.up(provider=self.vagrant_backend, vm_name=vm_name)
                print 'Vagrant Environment created! Access your stack with "nepho stack access <cloudlet> <blueprint>" or "vagrant ssh"'
            except subprocess.CalledProcessError:
                print "Vagrant exited with non-zero code, but your VM is likely running. Please use the status subcommand to check."

    def status(self):
        with cwd(self.vagrantfile_path):
            v = vagrant.Vagrant()
            status = v.status()
            try:
                status['remote_user'] = v.user()
                status['hostname'] = v.hostname()
                status['port'] = v.port()
                status['keyfile'] = v.keyfile()
                status['conf'] = v.conf()
            except Exception:
                pass

            print "User:      %s" % status['remote_user']
            print "Hostname:  %s" % status['hostname']
            print "Port:      %s" % status['port']
            print "Keyfile:   %s" % status['keyfile']
            print "Conf:      %s" % status['conf']

    def access(self):
        with cwd(self.vagrantfile_path):
            v = vagrant.Vagrant()
            ssh_connect_string = v.user_hostname_port()
            vagrant_binary = vagrant.VAGRANT_EXE
            os.execlp(vagrant_binary, "", "ssh")

    def destroy(self):
        """Bring down a vagrant instance."""
        with cwd(self.vagrantfile_path):
            v = vagrant.Vagrant()
            v.destroy()

    def _vm_name(self):
        """Helper method to generate the name for this VM."""
        cloudlet_name = self.scenario.cloudlet.name
        blueprint_name = self.scenario.blueprint.name
        return "%s-%s" % (cloudlet_name, blueprint_name)
