<template>
    <div :id="elId"
         dir="ltr"
         :style="styles"></div>
</template>

<script>
import { normalizeJsonSchema } from "../../utility/json-schema";
import { guid, cultureManager } from "libj-core";
import { isVoid } from "./util";
import reduce from 'lodash.reduce';
var localize = require('./ajv-i18n/_all');
export default {
    props: {
        styles: {
            type: String,
            default: 'width: 100%; height: 300px'
        },
        schema: {
            type: String
        },
        value: {
            type: String
        },
        /**
         * modes: tree, view, form, text
         */
        mode: {
            type: String,
            default: 'tree'
        },
    },
    data() {
        return {
            elId: guid.newId(),
            editor: null,
            validator: null,
            ajv: new Ajv({ allErrors: true, verbose: true })
        };
    },
    mounted() {
        var container = document.getElementById(this.elId);
        var options = {
            mode: this.mode,
            onChangeText: json => this.$emit('input', json),
            ajv: this.ajv
        };
        this.editor = new JSONEditor(container, options);
        this.setSchema();
        this.editor.set(this.parse(this.value));
        $('.jsoneditor-treepath').attr('draggable', 'true');
        var self = this;
        $(document).on('dragstart', '.jsoneditor-treepath', function (e) {
            var path = self.getSelectedPath();
            if (isVoid(path)) {
                return;
            }
            var model = {
                type: 'LiquidVariable',
                text: path,
                tag: self.parse(self.value)
            };
            e.originalEvent.dataTransfer.setData('Text', JSON.stringify(model));
        });
    },
    methods: {
        expandAll() {
            this.editor.expandAll();
        },
        parse(json) {
            try {
                return isVoid(json) || json.length === 0 ? {} : JSON.parse(json);
            } catch (e) {
                return {};
            }
        },
        validate() {
            var k = this.editor.get();
            var valid = this.validator(k);
            if (valid) {
                return null;
            }
            var culture = cultureManager.getActiveCulture().code;
            var fallbackCulture = cultureManager.getFallbackCulture().code;
            var loc = isVoid(localize[culture]) ? localize[fallbackCulture] : localize[culture];
            loc(this.validator.errors);
            var x = this.ajv.errorsText(this.validator.errors, { separator: '\n' });
            return x;
        },
        setSchema() {
            var k = normalizeJsonSchema(this.schema);
            var s = JSON.parse(k);
            this.validator = this.ajv.compile(s);
            this.editor.setSchema(s);
        },
        getSelectedPath() {
            var path = [];
            $(`#${this.elId}`).find('.jsoneditor-treepath-element')
                .each(function (index, element) {
                    if (index > 0) {
                        path.push(element.innerHTML);
                    }
                });
            if (path.length === 0) {
                return null;
            }
            if (path.length === 1 && (path[0] === 'undefined' || path[0].length === 0)) {
                return null;
            }
            var p = reduce(path, (sofar, value, index) => {
                if (index === 0) {
                    return value;
                }
                var isNumber = false;
                var num;
                try {
                    num = parseInt(value);
                    isNumber = !isNaN(num);
                } catch (eeee) {
                }
                if (isNumber) {
                    return `${sofar}[${num}]`;
                }
                return `${sofar}.${value}`;
            }, '');
            return p;
        }
    },
    watch: {
        value() {
            var newValue = this.value;
            var oldValue = this.editor.getText();
            if (oldValue !== newValue) {
                this.editor.set(this.parse(newValue));
            }
        },
        schema() {
            this.setSchema();
        },
        mode() {
            this.editor.setMode(this.mode);
        }
    }
}
</script>