# -*- coding: utf-8 -*-
import os
import sys
import json
import argparse
import fnmatch
from six import iteritems


RESULT_TEMPLATE = {
    'openapi': '3.0.0',
    'info': {
        'title': 'Distribution API',
        'version': '1.0'
    },
    'servers': [],
    'paths': {},
    'components': {
        'schemas': {}
    }
}

FOLDERS = ('components', 'common', 'content_types')
CURRENT_PATH = os.path.dirname(os.path.abspath(__file__))


def _nested_lookup(search_key, document, parent=None, parent_key=None):
    """Lookup a key in a nested dict, yield the dict and the parent dict that holds the key"""
    if isinstance(document, dict):
        for key, value in iteritems(document):
            if search_key == key:
                yield key, value, parent, parent_key
            elif isinstance(value, dict):
                for k, v, parent, parent_key in _nested_lookup(search_key, value, parent=document,
                                                               parent_key=key):
                    yield k, v, parent, parent_key


def add_schemas(path_to_json, schemas):
    """ Add all schemas in given path to the schemas array """
    json_files = [js for js in os.listdir(path_to_json) if js.endswith('.json')]

    for index, js in enumerate(json_files):
        with open(os.path.join(path_to_json, js)) as json_file:
            schemas[js.split('.')[0]] = json.load(json_file)


def retrieve_model(file_name):
    """ Build schema model recursively """
    key = '$ref'
    with open(file_name) as model_file:
        model_json = json.load(model_file)
    for k, v, parent, parent_key in _nested_lookup(key, model_json):
        file_name = v.split('/')[-1] + '.json'
        parent[parent_key] = retrieve_model(search_file(CURRENT_PATH, file_name))
    return model_json


def search_file(directory, filename):
    """ Search file in given directory"""
    for root, dirs, files in os.walk(directory):
        for basename in files:
            if fnmatch.fnmatch(basename, filename):
                filename = os.path.join(root, basename)
                return filename


if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='Build schemas.')
    parser.add_argument('--spec', dest='spec', action="store_true",
                        help='a flag to build the full spec')
    parser.add_argument('--model', dest='model', action="store", help='Model to build')

    args = parser.parse_args()

    if args.spec:
        for folder in FOLDERS:
            add_schemas(os.path.join(CURRENT_PATH, folder),
                        RESULT_TEMPLATE['components']['schemas'])

        with open('result.json', 'w') as fp:
            json.dump(RESULT_TEMPLATE, fp)
        print 'Schema exported to result.json file.'
    else:
        if args.model is not None:
            key = '$ref'
            model_json = retrieve_model(os.path.join(CURRENT_PATH, args.model + '.json')    )
            print json.dumps(model_json)
            print 'exit.'
        else:
            print "Model can't be none"
            sys.exit(1)
