#!/usr/bin/env python

from functools import wraps
import logging
import getopt
import sys
import json
import shlex
import re

from requests import Session

class ApiError(Exception):
    pass

def status_ok(f):
    @wraps(f)
    def wrapper(self, *args, **kwds):
        r = f(self, *args, **kwds)
        if r.status_code != 200:
            raise ApiError(str(r.status_code))
        return r
    return wrapper


def result_ok(f):
    @wraps(f)
    def wrapper(self, *args, **kwds):
        r = f(self, *args, **kwds)
        j = r.json()
        if 'result' in j:
            return j['result']
        if 'error' in j:
            logging.error('API ERROR %s', j['error'])
            raise ApiError(j['error'])
        return None
    return wrapper


class Api():
    def __init__(self, api_root):
        self.root = api_root
        self.api_root = api_root
        self.session = Session()
        self.result = None

    def http(self, f, url, data=None, json=None, params=None, files=None):
        if f == 'post':
            self.result = self.session.post(url, verify=False, data=data, json=json, files=files)
        elif f == 'put':
            self.result = self.session.put(url, verify=False, data=data, json=json)
        elif f == 'get':
            self.result = self.session.get(url, verify=False, params=params)
        elif f == 'delete':
            self.result = self.session.delete(url, verify=False, params=params)
        else:
            return None
        logging.debug("request  headers: %s", self.result.request.headers)
        logging.debug("response headers: %s", self.result.headers)
        return self.result

    @status_ok
    def api_call(self, f, path, json=None, data=None, params=None, files=None):
        return self.http(f, self.api_root + path, data, json, params, files)

    def login(self, username, password):
        self.http('post', self.api_root + '/api/login', json={'user': username, 'password': password})

    def logout(self):
        self.http('post', self.api_root + '/api/logout')

if __name__ == "__main__":
    show_headers = False
    api = None

    def get_vendor(id):
        try:
            api.api_call('get', '/api/system/vendor/' + 'VENDOR_' + id + '_ID')
            if 'result' in api.result.json():
                return api.result.json()['result']
        except Exception as e:
            print ("Failed call", str(e))
        return None

    def put_vendor(id, v):
        try:
            api.api_call('put', '/api/system/vendor/' + 'VENDOR_' + id + '_ID', json={'value': v})
            return api.result.json()['result']
        except Exception as e:
            print ("Failed call", str(e))
        return None

    try:
        opts, args = getopt.getopt(sys.argv[1:],
                                   "h:u:p:w:i:",
                                   ["host=", "user=", "pass=", "id=", "write="])
    except getopt.GetoptError as err:
        # print help information and exit:
        print(str(err))
        sys.exit(2)

    loglevel = logging.ERROR
    user = 'admin'
    passwd = 'admin'
    id = 'LAN_MAC'
    root = None
    write_value = None
    for o, a in opts:
        if o in ("-h", "--host"):
            if a.startswith('http://'):
                root = a
            elif a.startswith('https://'):
                root = a
            else:
                root = 'http://' + a
        elif o in ("-u", "--user"):
            user = a
        elif o in ("-p", "--pass"):
            passwd = a
        elif o in ("-w", "--write"):
            write_value = a
        elif o in ("-i", "--id"):
            id = a
        else:
            assert False, "unhandled option"

    logging.basicConfig(level=loglevel)

    ids = ('LAN_MAC','WIFI_MAC','BT_MAC','SN','CUSTOM')

    if root is None or (id not in ids):
        print("spotbox_vendor -h hostip -i <id>")
        print("   where id in %s" % ' '.join(ids))
        exit(-1)

    api = Api(root)

    api.login(user, passwd)

    if write_value is not None:
        if id == 'LAN_MAC':
            if len(write_value.split(',')) == 1:
                write_value = write_value + ',' + write_value
        put_vendor(id, write_value)
    else:
        print(json.dumps(get_vendor(id)))
    api.logout()

    logging.shutdown()
