import os
import argparse

from flask import Flask, request
from flask_restful import Resource, Api
from werkzeug.exceptions import HTTPException

from uncloud.common.shared import shared

app = Flask(__name__)
api = Api(app)

app.logger.handlers.clear()

DEFAULT_PORT=1234

arg_parser = argparse.ArgumentParser('metadata', add_help=False)
arg_parser.add_argument('--port', '-p', default=DEFAULT_PORT, help='By default bind to port {}'.format(DEFAULT_PORT))


@app.errorhandler(Exception)
def handle_exception(e):
    app.logger.error(e)
    # pass through HTTP errors
    if isinstance(e, HTTPException):
        return e

    # now you're handling non-HTTP exceptions only
    return {"message": "Server Error"}, 500


def get_vm_entry(mac_addr):
    return next(
        filter(
            lambda vm: mac_addr in list(zip(*vm.network))[1],
            shared.vm_pool.vms,
        ),
        None,
    )


# https://stackoverflow.com/questions/37140846/how-to-convert-ipv6-link-local-address-to-mac-address-in-python
def ipv62mac(ipv6):
    # remove subnet info if given
    subnet_index = ipv6.find("/")
    if subnet_index != -1:
        ipv6 = ipv6[:subnet_index]

    ipv6_parts = ipv6.split(":")
    mac_parts = list()
    for ipv6_part in ipv6_parts[-4:]:
        while len(ipv6_part) < 4:
            ipv6_part = "0" + ipv6_part
        mac_parts.append(ipv6_part[:2])
        mac_parts.append(ipv6_part[-2:])

    # modify parts to match MAC value
    mac_parts[0] = "%02x" % (int(mac_parts[0], 16) ^ 2)
    del mac_parts[4]
    del mac_parts[3]
    return ":".join(mac_parts)


class Root(Resource):
    @staticmethod
    def get():
        data = get_vm_entry(ipv62mac(request.remote_addr))

        if not data:
            return (
                {"message": "Metadata for such VM does not exists."},
                404,
            )
        else:
            etcd_key = os.path.join(
                shared.settings["etcd"]["user_prefix"],
                data.value["owner_realm"],
                data.value["owner"],
                "key",
            )
            etcd_entry = shared.etcd_client.get_prefix(
                etcd_key, value_in_json=True
            )
            user_personal_ssh_keys = [key.value for key in etcd_entry]
            data.value["metadata"]["ssh-keys"] += user_personal_ssh_keys
            return data.value["metadata"], 200


api.add_resource(Root, "/")


def main(arguments):
    port = arguments['port']
    debug = arguments['debug']
    app.run(debug=debug, host="::", port=port)
