/*
 * 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 _ from 'lodash';

import {Bean} from './Beans';

import AbstractTransformer from './AbstractTransformer';
import StringBuilder from './StringBuilder';
import VersionService from 'app/services/Version.service';

const versionService = new VersionService();

export default class IgniteSpringTransformer extends AbstractTransformer {
    static escapeXml(str = '') {
        return str.replace(/&/g, '&amp;')
            .replace(/"/g, '&quot;')
            .replace(/'/g, '&apos;')
            .replace(/>/g, '&gt;')
            .replace(/</g, '&lt;');
    }

    static commentBlock(sb, ...lines) {
        if (lines.length > 1) {
            sb.append('<!--');

            _.forEach(lines, (line) => sb.append(`  ${line}`));

            sb.append('-->');
        }
        else
            sb.append(`<!-- ${_.head(lines)} -->`);
    }

    static appendBean(sb, bean, appendId) {
        const beanTags = [];

        if (appendId)
            beanTags.push(`id="${bean.id}"`);

        beanTags.push(`class="${bean.clsName}"`);

        if (bean.factoryMtd)
            beanTags.push(`factory-method="${bean.factoryMtd}"`);

        sb.startBlock(`<bean ${beanTags.join(' ')}>`);

        _.forEach(bean.arguments, (arg) => {
            if (arg.clsName === 'MAP') {
                sb.startBlock('<constructor-arg>');
                this._constructMap(sb, arg);
                sb.endBlock('</constructor-arg>');
            }
            else if (_.isNil(arg.value)) {
                sb.startBlock('<constructor-arg>');
                sb.append('<null/>');
                sb.endBlock('</constructor-arg>');
            }
            else if (arg.constant) {
                sb.startBlock('<constructor-arg>');
                sb.append(`<util:constant static-field="${arg.clsName}.${arg.value}"/>`);
                sb.endBlock('</constructor-arg>');
            }
            else if (arg.clsName === 'BEAN') {
                sb.startBlock('<constructor-arg>');
                this.appendBean(sb, arg.value);
                sb.endBlock('</constructor-arg>');
            }
            else
                sb.append(`<constructor-arg value="${this._toObject(arg.clsName, arg.value)}"/>`);
        });

        this._setProperties(sb, bean);

        sb.endBlock('</bean>');
    }

    static _toObject(clsName, val) {
        const items = _.isArray(val) ? val : [val];

        if (clsName === 'EVENTS')
            return ['<list>', ..._.map(items, (item) => `    <util:constant static-field="${item.class}.${item.label}"/>`), '</list>'];

        return _.map(items, (item) => {
            switch (clsName) {
                case 'PROPERTY':
                case 'PROPERTY_CHAR':
                case 'PROPERTY_INT':
                    return `\${${item}}`;
                case 'java.lang.Class':
                    return this.javaTypes.fullClassName(item);
                case 'long':
                    return `${item}`;
                case 'java.lang.String':
                case 'PATH':
                case 'PATH_ARRAY':
                    return this.escapeXml(item);
                default:
                    return item;
            }
        });
    }

    static _isBean(clsName) {
        return this.javaTypes.nonBuiltInClass(clsName) && this.javaTypesNonEnum.nonEnum(clsName) && _.includes(clsName, '.');
    }

    static _setCollection(sb, prop) {
        sb.startBlock(`<property name="${prop.name}">`);
        sb.startBlock('<list>');

        _.forEach(prop.items, (item, idx) => {
            if (this._isBean(prop.typeClsName)) {
                if (idx !== 0)
                    sb.emptyLine();

                this.appendBean(sb, item);
            }
            else
                sb.append(`<value>${item}</value>`);
        });

        sb.endBlock('</list>');
        sb.endBlock('</property>');
    }

    static _constructMap(sb, map) {
        sb.startBlock('<map>');

        _.forEach(map.entries, (entry) => {
            const key = entry[map.keyField];
            const val = entry[map.valField];

            const isKeyBean = key instanceof Bean || this._isBean(map.keyClsName);
            const isValBean = val instanceof Bean || this._isBean(map.valClsName);


            if (isKeyBean || isValBean) {
                sb.startBlock('<entry>');

                sb.startBlock('<key>');
                if (isKeyBean)
                    this.appendBean(sb, key);
                else
                    sb.append(this._toObject(map.keyClsName, key));
                sb.endBlock('</key>');

                if (!_.isArray(val))
                    sb.startBlock('<value>');

                if (isValBean)
                    this.appendBean(sb, val);
                else
                    sb.append(this._toObject(map.valClsNameShow || map.valClsName, val));

                if (!_.isArray(val))
                    sb.endBlock('</value>');

                sb.endBlock('</entry>');
            }
            else
                sb.append(`<entry key="${this._toObject(map.keyClsName, key)}" value="${this._toObject(map.valClsName, val)}"/>`);
        });

        sb.endBlock('</map>');
    }

    /**
     *
     * @param {StringBuilder} sb
     * @param {Bean} bean
     * @returns {StringBuilder}
     */
    static _setProperties(sb, bean) {
        _.forEach(bean.properties, (prop, idx) => {
            switch (prop.clsName) {
                case 'DATA_SOURCE':
                    const valAttr = prop.name === 'dataSource' ? 'ref' : 'value';

                    sb.append(`<property name="${prop.name}" ${valAttr}="${prop.id}"/>`);

                    break;
                case 'EVENT_TYPES':
                    sb.startBlock(`<property name="${prop.name}">`);

                    if (prop.eventTypes.length === 1) {
                        const evtGrp = _.head(prop.eventTypes);

                        sb.append(`<util:constant static-field="${evtGrp.class}.${evtGrp.label}"/>`);
                    }
                    else {
                        sb.startBlock('<list>');

                        _.forEach(prop.eventTypes, (evtGrp, ix) => {
                            ix > 0 && sb.emptyLine();

                            sb.append(`<!-- EventType.${evtGrp.label} -->`);

                            _.forEach(evtGrp.events, (event) =>
                                sb.append(`<util:constant static-field="${evtGrp.class}.${event}"/>`));
                        });

                        sb.endBlock('</list>');
                    }

                    sb.endBlock('</property>');

                    break;
                case 'ARRAY':
                case 'PATH_ARRAY':
                case 'COLLECTION':
                    this._setCollection(sb, prop);

                    break;
                case 'MAP':
                    sb.startBlock(`<property name="${prop.name}">`);

                    this._constructMap(sb, prop);

                    sb.endBlock('</property>');

                    break;
                case 'java.util.Properties':
                    sb.startBlock(`<property name="${prop.name}">`);
                    sb.startBlock('<props>');

                    _.forEach(prop.entries, (entry) => {
                        sb.append(`<prop key="${entry.name}">${entry.value}</prop>`);
                    });

                    sb.endBlock('</props>');
                    sb.endBlock('</property>');

                    break;
                case 'BEAN':
                    sb.startBlock(`<property name="${prop.name}">`);

                    this.appendBean(sb, prop.value);

                    sb.endBlock('</property>');

                    break;
                default:
                    sb.append(`<property name="${prop.name}" value="${this._toObject(prop.clsName, prop.value)}"/>`);
            }

            this._emptyLineIfNeeded(sb, bean.properties, idx);
        });

        return sb;
    }

    /**
     * Build final XML.
     *
     * @param {Bean} cfg Ignite configuration.
     * @param {Object} targetVer Version of Ignite for generated project.
     * @param {Boolean} clientNearCaches
     * @returns {StringBuilder}
     */
    static igniteConfiguration(cfg, targetVer, clientNearCaches) {
        const available = versionService.since.bind(versionService, targetVer.ignite);

        const sb = new StringBuilder();

        // 0. Add header.
        sb.append('<?xml version="1.0" encoding="UTF-8"?>');
        sb.emptyLine();

        this.mainComment(sb);
        sb.emptyLine();

        // 1. Start beans section.
        sb.startBlock([
            '<beans xmlns="http://www.springframework.org/schema/beans"',
            '       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"',
            '       xmlns:util="http://www.springframework.org/schema/util"',
            '       xsi:schemaLocation="http://www.springframework.org/schema/beans',
            '                           http://www.springframework.org/schema/beans/spring-beans.xsd',
            '                           http://www.springframework.org/schema/util',
            '                           http://www.springframework.org/schema/util/spring-util.xsd">']);

        // 2. Add external property file
        if (this.hasProperties(cfg)) {
            this.commentBlock(sb, 'Load external properties file.');

            sb.startBlock('<bean id="placeholderConfig" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">');
            sb.append('<property name="location" value="classpath:secret.properties"/>');
            sb.endBlock('</bean>');

            sb.emptyLine();
        }

        // 3. Add data sources.
        const dataSources = this.collectDataSources(cfg);

        if (dataSources.length) {
            this.commentBlock(sb, 'Data source beans will be initialized from external properties file.');

            _.forEach(dataSources, (ds) => {
                this.appendBean(sb, ds, true);

                sb.emptyLine();
            });
        }

        _.forEach(clientNearCaches, (cache) => {
            this.commentBlock(sb, `Configuration of near cache for cache "${cache.name}"`);

            this.appendBean(sb, this.generator.cacheNearClient(cache, available), true);

            sb.emptyLine();
        });

        // 3. Add main content.
        this.appendBean(sb, cfg);

        // 4. Close beans section.
        sb.endBlock('</beans>');

        return sb;
    }

    static cluster(cluster, targetVer, client) {
        const cfg = this.generator.igniteConfiguration(cluster, targetVer, client);

        const clientNearCaches = client ? _.filter(cluster.caches, (cache) =>
            cache.cacheMode === 'PARTITIONED' && _.get(cache, 'clientNearConfiguration.enabled')) : [];

        return this.igniteConfiguration(cfg, targetVer, clientNearCaches);
    }
}
