/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
import CodeMirror from 'codemirror';
import {YAMLException} from 'js-yaml';
import {JsYamlParser} from '../../JsYamlParser';
import {Validator} from 'jsonschema';
import blueprintSchema from '../schemas/blueprint.json';
import blueprintEntitySchema from '../schemas/blueprint-entity.json';
import blueprintLocationSchema from '../schemas/blueprint-location.json';
import catalogSchema from '../schemas/catalog.json';
import catalogItemReferenceSchema from '../schemas/catalog-item-reference.json';
import catalogItemInlineSchema from '../schemas/catalog-item-inline.json';
import catalogVersionSchema from '../schemas/catalog-version.json';
import rootSchema from '../schemas/root.json';

CodeMirror.registerGlobalHelper('lint', 'yamlBlueprint', (mode, cm) => (mode.name === 'yaml' && mode.type === 'blueprint'), (text, options, cm) => {
    let validator = new Validator();

    validator.addSchema(JSON.parse(blueprintSchema), '/Blueprint');
    validator.addSchema(JSON.parse(blueprintEntitySchema), '/Blueprint/Entity');
    validator.addSchema(JSON.parse(blueprintLocationSchema), '/Blueprint/Location');

    return lint(validator, blueprintSchema, text, options, cm);
});
CodeMirror.registerGlobalHelper('lint', 'yamlCatalog', (mode, cm) => (mode.name === 'yaml' && mode.type === 'catalog'), (text, options, cm) => {
    let validator = new Validator();

    validator.addSchema(JSON.parse(catalogSchema), '/Catalog');
    validator.addSchema(JSON.parse(catalogItemReferenceSchema), '/Catalog/Item/Reference');
    validator.addSchema(JSON.parse(catalogItemInlineSchema), '/Catalog/Item/Inline');
    validator.addSchema(JSON.parse(catalogVersionSchema), '/Catalog/Version');
    // below are needed for catalog items
    validator.addSchema(JSON.parse(blueprintSchema), '/Blueprint');
    validator.addSchema(JSON.parse(blueprintEntitySchema), '/Blueprint/Entity');
    validator.addSchema(JSON.parse(blueprintLocationSchema), '/Blueprint/Location');

    return lint(validator, catalogSchema, text, options, cm);
});
CodeMirror.registerGlobalHelper('lint', 'yamlBrooklyn', (mode, cm) => (mode.name === 'yaml' && mode.type === 'brooklyn'), (text, options, cm) => {
    let validator = new Validator();

    validator.addSchema(JSON.parse(blueprintSchema), '/Blueprint');
    validator.addSchema(JSON.parse(blueprintEntitySchema), '/Blueprint/Entity');
    validator.addSchema(JSON.parse(blueprintLocationSchema), '/Blueprint/Location');
    validator.addSchema(JSON.parse(catalogSchema), '/Catalog');
    validator.addSchema(JSON.parse(catalogItemReferenceSchema), '/Catalog/Item/Reference');
    validator.addSchema(JSON.parse(catalogItemInlineSchema), '/Catalog/Item/Inline');
    validator.addSchema(JSON.parse(catalogVersionSchema), '/Catalog/Version');

    return lint(validator, rootSchema, text, options, cm);
});

function lint(validator, baseSchema, text, options, cm) {
    let issues = [];
    let parser = new JsYamlParser();

    try {
        let root = parser.parse(text);

        if (root) {
            validator.validate(root.result, JSON.parse(baseSchema), {propertyName: 'blueprint', nestedErrors: true}).errors.forEach(error => {
                let from = CodeMirror.Pos(0, 0);
                let to = CodeMirror.Pos(0, 0);
                let yamlNode = findYamlNode(root, error.instance);

                if (yamlNode) {
                    switch (error.name) {
                        case 'anyOf':
                        case 'oneOf':
                        case 'allOf':
                        case 'not':
                        case 'required':
                            from = to = getPostFromIndex(yamlNode.start, cm);
                            break;
                        case 'additionalProperties':
                            let childNode = yamlNode.children.find(child => child.result === error.argument);
                            from = getPostFromIndex(childNode.start, cm);
                            to = getPostFromIndex(childNode.end, cm);
                            break;
                        default:
                            from = getPostFromIndex(yamlNode.start, cm);
                            to = getPostFromIndex(yamlNode.end, cm);
                            break;
                    }
                }
                issues.push({
                    from: from,
                    to: to,
                    message: error.stack
                });
            });
        }
    } catch (err) {
        if (err instanceof YAMLException) {
            // Inspire by the Mark.getSnippet() code: https://github.com/nodeca/js-yaml/blob/master/lib/js-yaml/mark.js#L16-L52
            let start = err.mark.position;
            while (start > 0 && '\x00\r\n\x85\u2028\u2029'.indexOf(err.mark.buffer.charAt(start - 1)) === -1) {
                start--;
            }
            let end = err.mark.position - start;
            let errorText = err.mark.buffer.substr(start, end);

            issues.push({
                from: CodeMirror.Pos(err.mark.line, cm.getLine(err.mark.line).indexOf(errorText)),
                to: CodeMirror.Pos(err.mark.line, cm.getLine(err.mark.line).indexOf(errorText) + (errorText.length > 0 ? errorText.length : 1)),
                message: err.reason
            });
        } else {
            issues.push({
                from: CodeMirror.Pos(0, 0),
                to: CodeMirror.Pos(0, 0),
                message: err.message
            });
        }
    }

    return issues;
}

function findYamlNode(node, search) {
    if (node.result === search) {
        return node;
    }

    for (let i = 0; i < node.children.length; i++) {
        let found = findYamlNode(node.children[i], search);
        if (found) {
            return found;
        }
    }
}

function getPostFromIndex(index, cm) {
    let total = cm.lineCount(), pos = 0, line, ch, len;
    for (line = 0; line < total; line++) {
        len = cm.getLine(line).length + 1;
        if (pos + len > index) { ch = index - pos; break; }
        pos += len;
    }
    return CodeMirror.Pos(line, ch);
}