/**
 * Copyright (C) 2006-2017 Talend Inc. - www.talend.com
 *
 * Licensed 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.
 */
package org.talend.sdk.component.studio.model.parameter;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

import org.talend.core.model.process.EComponentCategory;
import org.talend.core.model.process.INode;
import org.talend.designer.core.model.components.ElementParameter;
import org.talend.sdk.component.server.front.model.PropertyValidation;

/**
 * Creates properties from leafs
 */
public class SettingsCreator implements PropertyVisitor {

    /**
     * {@link ElementParameter} has numRow field which stores widget relative position (row number on which it
     * appears)
     * If numRow = 10, this does not necessarily mean that widget will be shown on 10th line,
     * but when 1 parameter has numRow = 8, and 2 has numRow = 10, then 2 will shown under 1
     */
    private int lastRowNumber = 1;

    /**
     * Node for which parameters are created. It is required to set {@link ElementParameter} constructor
     */
    private final INode iNode;

    /**
     * Stores configuration parameters for {@link INode}
     */
    private List<ElementParameter> settings = new ArrayList<>();

    public SettingsCreator(final INode iNode) {
        this.iNode = iNode;
    }

    public List<ElementParameter> getSettings() {
        return Collections.unmodifiableList(settings);
    }

    /**
     * Creates ElementParameters only from leafs
     * 
     */
    @Override
    public void visit(final PropertyNode node) {
        if (node.isLeaf()) {
            switch (node.getFieldType()) {
            case CHECK:
                visitCheck(node);
                break;
            case CLOSED_LIST:
                visitClosedList(node);
                break;
            case MEMO_JAVA:
                visitMemoJava(node);
                break;
            case HIDDEN_TEXT:
            case TEXT:
                visitText(node);
                break;
            default:
                visitDefault(node);
            }
            createParameter(node);
        }
    }

    /**
     * Creates {@link ElementParameter} for Check field type and adds it to settings
     * Sets false as default value
     */
    private void visitCheck(final PropertyNode node) {
        ElementParameter parameter = createParameter(node);
        parameter.setValue(false);
        settings.add(parameter);
    }

    /**
     * Creates {@link ElementParameter} for Closed List field type and adds it to settings
     * Sets Closed List possible values and sets 1st element as default
     */
    private void visitClosedList(final PropertyNode node) {
        ElementParameter parameter = createParameter(node);
        PropertyValidation validation = node.getProperty().getValidation();
        if (validation == null) {
            throw new IllegalArgumentException("validation should not be null");
        }
        Collection<String> possibleValues = validation.getEnumValues();
        if (possibleValues == null) {
            throw new IllegalArgumentException("validation enum values should not be null");
        }
        parameter.setListItemsValue(possibleValues.toArray());
        parameter.setListItemsDisplayName(possibleValues.toArray(new String[0]));
        parameter.setListItemsDisplayCodeName(possibleValues.toArray(new String[0]));
        parameter.setListItemsReadOnlyIf(new String[possibleValues.size()]);
        parameter.setListItemsNotReadOnlyIf(new String[possibleValues.size()]);
        parameter.setListItemsShowIf(new String[possibleValues.size()]);
        parameter.setListItemsNotShowIf(new String[possibleValues.size()]);
        if (!possibleValues.isEmpty()) {
            parameter.setValue(possibleValues.iterator().next());
        }
        settings.add(parameter);
    }

    /**
     * Creates {@link ElementParameter} for MemoJava field type and adds it to settings
     * Sets default value
     */
    private void visitMemoJava(final PropertyNode node) {
        ElementParameter parameter = createParameter(node);
        parameter.setValue("String foo = \"bar\";");
        settings.add(parameter);
    }

    /**
     * Creates {@link ElementParameter} for Text field type and adds it to settings
     * Sets "" as default value
     */
    private void visitText(final PropertyNode node) {
        ElementParameter parameter = createParameter(node);
        parameter.setValue("");
        settings.add(parameter);
    }

    /**
     * Creates {@link ElementParameter} for default parameter type and adds it to settings
     */
    private void visitDefault(final PropertyNode node) {
        settings.add(createParameter(node));
    }

    /**
     * Creates {@link ElementParameter} and sets common state for different types of parameters
     */
    private ElementParameter createParameter(final PropertyNode node) {
        ElementParameter parameter = new ElementParameter(iNode);
        // TODO implement category computing
        parameter.setCategory(EComponentCategory.BASIC);
        parameter.setDisplayName(node.getProperty().getDisplayName());
        parameter.setFieldType(node.getFieldType());
        parameter.setName(node.getProperty().getPath());
        parameter.setNumRow(lastRowNumber++);
        parameter.setShow(true);
        parameter.setValue("This is default value");
        return parameter;
    }

}

@@ -2185,89 +2185,8 @@
 ) %7B%0A
-            case CHECK:%0A                visitCheck(node);%0A                break;%0A
     
@@ -2289,634 +2289,76 @@
     
-case MEMO_JAVA:%0A                visitMemoJava(node);%0A                break;%0A            case HIDDEN_TEXT:%0A            case TEXT:%0A                visitText(node);%0A                break;%0A            default:%0A                visitDefault(node);%0A            %7D%0A            createParameter(node);%0A        %7D%0A    %7D%0A%0A    /**%0A     * Creates %7B@link ElementParameter%7D for Check field type and adds it to settings%0A     * Sets false as default value%0A     */%0A    private void visitCheck(final PropertyNode node) %7B%0A        ElementParameter parameter = createParameter(node);%0A        parameter.setValue(false);%0A        settings.add(parameter);
+default:%0A                visitDefault(node);%0A            %7D%0A        %7D
 %0A   
@@ -3615,784 +3615,8 @@
 %5D);%0A
-        if (!possibleValues.isEmpty()) %7B%0A            parameter.setValue(possibleValues.iterator().next());%0A        %7D%0A        settings.add(parameter);%0A    %7D%0A%0A    /**%0A     * Creates %7B@link ElementParameter%7D for MemoJava field type and adds it to settings%0A     * Sets default value%0A     */%0A    private void visitMemoJava(final PropertyNode node) %7B%0A        ElementParameter parameter = createParameter(node);%0A        parameter.setValue(%22String foo = %5C%22bar%5C%22;%22);%0A        settings.add(parameter);%0A    %7D%0A%0A    /**%0A     * Creates %7B@link ElementParameter%7D for Text field type and adds it to settings%0A     * Sets %22%22 as default value%0A     */%0A    private void visitText(final PropertyNode node) %7B%0A        ElementParameter parameter = createParameter(node);%0A        parameter.setValue(%22%22);%0A
     
@@ -4510,31 +4510,44 @@
 lue(
-%22This is d
+node.getProperty().getD
 efault
- v
+V
 alue
-%22
+()
 );%0A 

set default value for ElementParameters