#!/usr/bin/env python3

# Copyright (c) 2020 cloudover.io
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

import os
os.environ['DINEMIC_CONFIG'] = '/etc/starsheep/config.dinemic'

import dinemic
import sys
import urllib.request
import yaml

from starsheep.context import Context
from starsheep.models.model import Model
from starsheep.command_line import get_url, load_application, import_application, import_data, apply_data, check_version


def print_help():
    print('Usage:')
    print('starsheep-cli get|list [filter or object_id] [--url=...] [--caller-id=...]')
    print('')
    print('\t--url=[path] - path to the yaml file. Default is /etc/starsheep/starsheep.yaml')
    print('\t--caller-id=[object id] - ID of object, which keys will be used to decrypt encrypted values. Object should be owned by node')


if __name__ == "__main__":
    options = sys.argv[1:]
    dinemic.prepare()

    ctx = Context()
    ctx.cmdline = options

    path = '/etc/starsheep/starsheep.yaml'
    caller_id = ''
    for i in range(len(options)):
        if i >= len(options):
            break
        opt = options[i]
        if opt.startswith('--url='):
            path = opt.split('=')[1]
            del options[i]
            i = i-1
        elif opt.startswith('--caller-id='):
            caller_id = opt.split('=')[1]
            del options[i]
            i = i-1

    if len(options) < 1 or options[0] not in ['get', 'list', 'delete']:
        print_help()
        sys.exit(1)

    f = urllib.request.urlopen(get_url(path))
    document = yaml.safe_load(f)
    f.close()

    check_version(document, ctx)
    import_application(document, ctx)
    load_application(document, ctx)

    if options[0] == 'get':
        models = {}
        for obj_id in options[1:]:
            model_data = {
            }

            model = Model.get_object(obj_id, caller_id, ctx)
            model_data['read_authorized_objects'] = []
            model_data['update_authorized_objects'] = []


            setattr(model, 'read_authorized_objects',
                    dinemic.DList('read_authorized_objects', False))
            getattr(model, 'read_authorized_objects')._object_id = model.get_db_id()
            getattr(model, 'read_authorized_objects')._caller_id = model.get_db_id()
            for i in range(model.read_authorized_objects.length()):
                model_data['read_authorized_objects'].append(model.read_authorized_objects.at(i))

            setattr(model, 'update_authorized_objects',
                    dinemic.DList('update_authorized_objects', False))
            getattr(model, 'update_authorized_objects')._object_id = model.get_db_id()
            getattr(model, 'update_authorized_objects')._caller_id = model.get_db_id()
            for i in range(model.update_authorized_objects.length()):
                model_data['update_authorized_objects'].append(model.update_authorized_objects.at(i))

            if ctx.models[model.get_model()].fields is not None:
                model_data['fields'] = {}
                for f in ctx.models[model.get_model()].fields:
                    model_data['fields'][f] = getattr(model, f).get()

            if ctx.models[model.get_model()].lists is not None:
                model_data['lists'] = {}
                for l in ctx.models[model.get_model()].lists:
                    l_items = []
                    for i in range(getattr(model, l).length()):
                        l_items.append(getattr(model, l).at(i))
                    model_data['lists'][l] = l_items

            if ctx.models[model.get_model()].dicts is not None:
                model_data['dicts'] = {}
                for d in ctx.models[model.get_model()].dicts:
                    d_items = {}
                    for k in getattr(model, d).keys():
                        d_items[k] = getattr(model, d).get(k)
                    model_data['dicts'][d] = d_items

            if model.get_model() not in models:
                models[model.get_model()] = {}

            models[model.get_model()][model.get_id()] = model_data

        print(yaml.safe_dump(models))
    elif options[0] == 'list':
        if len(options) <= 1:
            print(yaml.safe_dump(dinemic.object_list('')))
        else:
            if options[1] == '@':
                print(yaml.safe_dump(dinemic.object_list_owned('*')))
            else:
                print(yaml.safe_dump(dinemic.object_list(options[1])))
    else:
        print_help()
        sys.exit(1)
