#!/usr/bin/python
# Provides all the API functionality callable through "/api"

from flask import request
from flaskext.auth import login_required
from git import Repo
import security
import requests, json, re
import os, sys, imp, shutil

apiDict = {}
indexes = {}

def init():
    global modules
    modules = loadPlugins()
    return 0

def addToApi(custom, module, function):
    apiDict[custom] = [module, function]

def setConfig(cfg, orig_cfg):
    global config
    global originalCfg
    config = cfg
    originalCfg = orig_cfg

def getConfig():
    global config
    return config

def loadPlugins():
    plugin = {}
    plugin_dir = os.getcwd() + '/plugins/'
    for i in os.listdir(plugin_dir):
        if not i == '__init__.py' and i.endswith('.py'):
            name =  i.replace('.py', '')
            try:
               plugin[name] = imp.load_source(name, plugin_dir + i)
               plugin[name].init()
            except ImportError:
               print "Error occured during loading imports for the plugin " + name + ". Please check whether all dependecies are installed"
               sys.exit()
    return plugin

@login_required()
def gateway():
    requestedUrl = request.url.split("/api")
    custom = request.args.get('custom', '')
    if custom == "bar_chart":
        idxs = request.args.get('idxs', '')
        idxArray = idxs.split(",")
        resultArray = []
        resultDict = {}
        for i in idxArray:
            qResults = queryDomoticz("?type=devices&rid=" + i)
            jsonObj = json.loads(qResults)
            resultDict["y"] = jsonObj["result"][0]["Name"]
            resultDict["a"] = jsonObj["result"][0]["Data"]
            resultArray.append(resultDict.copy())
        result = json.dumps(resultArray)
    elif custom == "donut_chart":
        idxs = request.args.get('idxs', '')
        idxArray = idxs.split(",")
        resultArray = []
        resultDict = {}
        for i in idxArray:
            qResults = queryDomoticz("?type=devices&rid=" + i)
            jsonObj = json.loads(qResults)
            resultDict["label"] = jsonObj["result"][0]["Name"]
            resultDict["value"] = re.findall("\d+\.?\d+", jsonObj["result"][0]["Data"])
            resultArray.append(resultDict.copy())
        result = json.dumps(resultArray)
    elif custom == "modify_config":
        idx = request.args.get('idx', '')
        page = request.args.get('page', '')
        component = request.args.get('component', '')
        description = request.args.get('description', '')
        extra = request.args.get('extra', '')
        writeToConfig(idx, page, component, description, extra)
    elif custom == 'indexPlugins':
        result = json.dumps(indexPlugins(request.args))
    elif custom in apiDict:
        module = apiDict.get(custom)[0]
        function = apiDict.get(custom)[1]
        call = getattr(modules[module], function)
        result = call(request.args)
    else:
        result = queryDomoticz(requestedUrl[1])
    try:
    	if not is_json(result):
           result = json.dumps(result)
        return security.sanitizeJSON(json.loads(result))
    except:
        return "No results returned"

def is_json(myjson):
    try:
        json_object = json.loads(str(myjson))
    except ValueError, e:
        return False
    return True

def queryDomoticz(url):
    try:
        r = requests.get('http://' + config["general_settings"]["server"]["url"] + '/json.htm' + url,
        auth=(config["general_settings"]["server"].get("user"), config["general_settings"]["server"].get("password")), timeout=5.00)
    except:
        return
    return r.text

def writeToConfig(idx, page, component, description, extra):
    section = dict(originalCfg[page][component])
    section[description] = idx
    originalCfg[page][component] = section
    originalCfg.write()

def checkDomoticzStatus(config):
    domoticzDevices = []
    try:
        result = json.loads(queryDomoticz("?type=devices&filter=all"))
    except:
        print "Domoticz is not reachable."
	sys.exit()
    for device in result["result"]:
        domoticzDevices.append(device["idx"])
    configuredDevicesInDomoticz(config, domoticzDevices)

def configuredDevicesInDomoticz(config, domoticzDevices):
    for k, v in config.iteritems():
        if isinstance(v, dict):
            configuredDevicesInDomoticz(v, domoticzDevices)
        else:
            if isinstance(v, int):
                if v not in domoticzDevices:
                    print "Device with " + v + " is not available in Domoticz"
                    sys.exit()
            elif isinstance(v, list):
                if (v[0].isdigit()) and (v[0] not in domoticzDevices):
                    print "Device with " + v[0] + " is not available in Domoticz"
                    sys.exit()

def getPluginDict():
    global indexes
    return indexes

def setPluginDict(d):
    global indexes
    indexes = d

def getPluginVersion(loc):
    f = open(loc, 'r').read().split('\n')
    v = None
    for l in f:
        t = l.split('=')
        if t[0] == '@version':
            _tmp_v = t[1].split('.')
            c = 1
            _version = _tmp_v[0] + '.'
            while(c < len(_tmp_v)):
                _version += _tmp_v[c]
                c += 1
    return float(_version)

def indexPlugins(params={}):
    tmpFolder = 'static/tmp'
    indexFolderPath = 'static/tmp/pluginsIndex/'
    docsFolderPath = 'static/docs/'
    installedPlugins = []
    staticFolder = ['css/', 'images/', 'fonts/', 'js/']
    indexes = getPluginDict()
    pluginParts = ['templates/', 'plugins/']

    if 'action' in params:
        if not params['action'] == 'getPlugins':
            try:
                if not int(params['folid']) in indexes:
                    return "No valid plugin id specified."
            except:
                    return "Please specify integers only."

    if 'action' in params:
        if params['action'] == 'getPlugins':
            folders = filter(lambda x: os.path.isdir(os.path.join(indexFolderPath, x)),
                     os.listdir(indexFolderPath))
            for i in folders:
                i = security.sanitizePathBasename(i)
                if i != '.git':
                    fol = {}
                    fol['id'] = len(indexes)
                    fol['folder'] = i
                    fol['status'] = 'install'
                    for filename in os.listdir('plugins/'):
                        installedPlugins.append(filename)

                    for filename in os.listdir(indexFolderPath + i + '/plugins'):
                        if filename in installedPlugins:
                            installed_version = getPluginVersion(docsFolderPath + i + '_readme.md')
                            indexed_version = getPluginVersion(indexFolderPath + i + '/' + docsFolderPath + 'readme.md')
                            if indexed_version > installed_version:
                                fol['update'] = 'yes'
                            else:
                                fol['update'] = 'no'
                            fol['status'] = 'remove'
                    readme = open(indexFolderPath + i + '/' + docsFolderPath + 'readme.md', 'r').read().split('\n')
                    sumList = {}
                    for s in readme:
                        t = s.split('=')
                        if len(t) > 1:
                            fol[t[0].replace('@', '')] = t[1]
                    if not i in (f['folder'] for f in indexes.itervalues()):
                        indexes[len(indexes)] = fol
                    else:
                        for tmp in indexes.itervalues():
                            if i == tmp['folder']:
                                for k in fol:
                                    if k != 'id':
                                        indexes[tmp['id']][k] = fol[k]
            setPluginDict(indexes)
            return indexes
        elif params['action'] == 'installPlugin':
            if 'folid' in params:
                if indexes[int(params['folid'])]['status'] == 'install':
                    src_path = indexFolderPath + indexes[int(params['folid'])]['folder'] + '/'
                    for part in pluginParts:
                        for filename in os.listdir(src_path + part):
                            shutil.copy(src_path + part + filename, part + filename)
                    for f in staticFolder:
                        if os.path.exists(src_path + 'static/' + f):
                            for filename in os.listdir(src_path + '/static/' + f):
                                shutil.copy(src_path + 'static/' + f + filename, 'static/' + f + filename)
                    for filename in os.listdir(src_path + '/' + docsFolderPath):
                        shutil.copy(src_path + '/' + docsFolderPath + filename, docsFolderPath + indexes[int(params['folid'])]['folder'] + '_' + filename)
                    indexes[int(params['folid'])]['status'] = 'remove'
                    global modules
                    modules = loadPlugins()
                    return indexes[int(params['folid'])]['folder'] + ' installed.'
                else:
                    return "This plugin is already installed."
        elif params['action'] == 'removePlugin':
            if 'folid' in params:
                if indexes[int(params['folid'])]['status'] == 'remove':
                    src_path = indexFolderPath + indexes[int(params['folid'])]['folder'] + '/'
                    for part in pluginParts:
                        for filename in os.listdir(src_path + part):
                            os.remove(part + filename)
                    for f in staticFolder:
                        if os.path.exists(src_path + 'static/' + f):
                            for filename in os.listdir(src_path + 'static/' + f):
                                os.remove('static/' + f + filename)
                    for filename in os.listdir(src_path + '/' + docsFolderPath):
                        shutil.copy(src_path + '/' + docsFolderPath + filename, docsFolderPath + indexes[int(params['folid'])]['folder'] + '_' + filename)
                    indexes[int(params['folid'])]['status'] = 'install'
                    return indexes[int(params['folid'])]['folder'] + ' removed.'
                else:
                    return "This plugin was already removed."
        setPluginDict(indexes)
    else:
        if not os.path.exists(tmpFolder):
            os.makedirs(tmpFolder)
        if not os.path.exists(indexFolderPath):
            os.makedirs(indexFolderPath)
        else:
            shutil.rmtree(indexFolderPath)
            os.makedirs(indexFolderPath)
        Repo.clone_from("https://github.com/wez3/domoboard-plugins.git", indexFolderPath)
        folders = filter(lambda x: os.path.isdir(os.path.join(indexFolderPath, x)),
                         os.listdir(indexFolderPath))
        return indexPlugins({'action': 'getPlugins'})
