import hashlib
import os
import socket
import sys
import base64
import time
#import threading
import subprocess
import random
import tempfile
#from sshtunnel import SSHTunnelForwarder
from django.db.models import F, Q
from xos.config import Config
from synchronizers.base.syncstep import SyncStep
from synchronizers.base.ansible import run_template_ssh
from synchronizers.base.SyncInstanceUsingAnsible import SyncInstanceUsingAnsible
from core.models import Service, Slice
from services.monitoring.models import CeilometerService, MonitoringChannel
from xos.logger import Logger, logging

parentdir = os.path.join(os.path.dirname(__file__),"..")
sys.path.insert(0,parentdir)

logger = Logger(level=logging.INFO)

class SSHTunnel:

    def __init__(self, localip, localport, key, remoteip, remote_port, jumpuser, jumphost):
        self.key = key
        self.remote_host = remoteip        # Remote ip on remotehost
        self.remote_port = remote_port
        # Get a temporary file name
        tmpfile = tempfile.NamedTemporaryFile()
        tmpfile.close()
        self.socket = tmpfile.name
        self.local_port = localport
        self.local_host = localip
        self.jump_user = jumpuser        # Remote user on remotehost
        self.jump_host = jumphost        # What host do we send traffic to
        self.open = False

    def start(self):
        exit_status = subprocess.call(['ssh', '-MfN',
            '-S', self.socket,
            '-i', self.key,
            '-L', '{}:{}:{}:{}'.format(self.local_host, self.local_port, self.remote_host, self.remote_port),
            '-o', 'ExitOnForwardFailure=True',
            self.jump_user + '@' + self.jump_host
        ])
        if exit_status != 0:
            raise Exception('SSH tunnel failed with status: {}'.format(exit_status))
        if self.send_control_command('check') != 0:
            raise Exception('SSH tunnel failed to check')
        self.open = True

    def stop(self):
        if self.open:
            if self.send_control_command('exit') != 0:
                raise Exception('SSH tunnel failed to exit')
            self.open = False

    def send_control_command(self, cmd):
        return subprocess.check_call(['ssh', '-S', self.socket, '-O', cmd, '-l', self.jump_user, self.jump_host])

    def __enter__(self):
        self.start()
        return self

    def __exit__(self, type, value, traceback):
        self.stop()


#class SshTunnel(threading.Thread):
#    def __init__(self, localip, localport, remoteip, remoteport, proxy_ssh_key, jumpuser, jumphost):
#        threading.Thread.__init__(self)
#        self.localip = localip          # Local ip to listen to
#        self.localport = localport      # Local port to listen to
#        self.remoteip = remoteip        # Remote ip on remotehost
#        self.remoteport = remoteport    # Remote port on remotehost
#        self.proxy_ssh_key = proxy_ssh_key
#        self.jumpuser = jumpuser        # Remote user on remotehost
#        self.jumphost = jumphost        # What host do we send traffic to
#        self.daemon = True              # So that thread will exit when
#                                        # main non-daemon thread finishes
#
#    def run(self):
#        if subprocess.call([
#            'ssh', '-N',
#                   '-i', self.proxy_ssh_key,
#                   '-L', self.localip + ':' + str(self.localport) + ':' + self.remoteip + ':' + str(self.remoteport),
#                   jumpuser + '@' + jumphost ]):
#            raise Exception ('ssh tunnel setup failed')

class SyncMonitoringChannel(SyncInstanceUsingAnsible):
    provides=[MonitoringChannel]
    observes=MonitoringChannel
    requested_interval=0
    template_name = "sync_monitoringchannel.yaml"
    service_key_name = "/opt/xos/synchronizers/monitoring/monitoring_channel_private_key"

    def __init__(self, *args, **kwargs):
        super(SyncMonitoringChannel, self).__init__(*args, **kwargs)

    def fetch_pending(self, deleted):
        if (not deleted):
            objs = MonitoringChannel.get_tenant_objects().filter(Q(enacted__lt=F('updated')) | Q(enacted=None),Q(lazy_blocked=False))
        else:
            objs = MonitoringChannel.get_deleted_tenant_objects()

        return objs

    def get_extra_attributes(self, o):
        # This is a place to include extra attributes. In the case of Monitoring Channel, we need to know
        #   1) Allowed tenant ids
        #   2) Ceilometer API service endpoint URL if running externally
        #   3) Credentials to access Ceilometer API service

        ceilometer_services = CeilometerService.get_service_objects().filter(id=o.provider_service.id)
        if not ceilometer_services:
            raise "No associated Ceilometer service"
        ceilometer_service = ceilometer_services[0]
        ceilometer_pub_sub_url = ceilometer_service.ceilometer_pub_sub_url
        if not ceilometer_pub_sub_url:
            ceilometer_pub_sub_url = ''
        instance = self.get_instance(o)

        try:
            full_setup = Config().observer_full_setup
        except:
            full_setup = True

        fields = {"unique_id": o.id,
                  "allowed_tenant_ids": o.tenant_list,
                  "auth_url":ceilometer_service.ceilometer_auth_url,
                  "admin_user":ceilometer_service.ceilometer_admin_user,
                  "admin_password":ceilometer_service.ceilometer_admin_password,
                  "admin_tenant":ceilometer_service.ceilometer_admin_tenant,
                  "ceilometer_pub_sub_url": ceilometer_pub_sub_url,
                  "full_setup": full_setup}

        return fields

    def sync_fields(self, o, fields):
        try:
           super(SyncMonitoringChannel, self).sync_fields(o, fields)

           #Check if ssh tunnel is needed
           proxy_ssh = getattr(Config(), "observer_proxy_ssh", False)

           if proxy_ssh:
               proxy_ssh_key = getattr(Config(), "observer_proxy_ssh_key", None)
               proxy_ssh_user = getattr(Config(), "observer_proxy_ssh_user", "root")
               jump_hostname = fields["hostname"]

               #Get the tunnel detsination               
               remote_host = o.private_ip
               remote_port = o.ceilometer_port
               #FIXME: For now, trying to setup the tunnel on the local port same as the remote port
               local_port = remote_port
               local_ip = socket.gethostbyname(socket.gethostname())

#               tunnel = SSHTunnelForwarder(jump_hostname,
#                                      ssh_username=proxy_ssh_user,
#                                      ssh_pkey=proxy_ssh_key,
#                                      ssh_private_key_password="",
#                                      remote_bind_address=(remote_host,remote_port),
#                                      local_bind_address=(local_ip,local_port),
#                                      set_keepalive=300)
#               tunnel.start()
               tunnel = SSHTunnel(local_ip, local_port, proxy_ssh_key, remote_host, remote_port, proxy_ssh_user, jump_hostname)
               tunnel.start()

               #Update the model with ssh tunnel info
               o.ssh_proxy_tunnel = True
               o.ssh_tunnel_ip = local_ip
               o.ssh_tunnel_port = local_port

        except Exception,error:
           raise Exception(error)

    def run_playbook(self, o, fields):
        #ansible_hash = hashlib.md5(repr(sorted(fields.items()))).hexdigest()
        #quick_update = (o.last_ansible_hash == ansible_hash)

        #if quick_update:
        #    logger.info("quick_update triggered; skipping ansible recipe")
        #else:
        super(SyncMonitoringChannel, self).run_playbook(o, fields)

        #o.last_ansible_hash = ansible_hash

    def map_delete_inputs(self, o):
        fields = {"unique_id": o.id,
                  "delete": True}
        return fields
