/*
 * Licensed to Crate.io GmbH ("Crate") under one or more contributor
 * license agreements.  See the NOTICE file distributed with this work for
 * additional information regarding copyright ownership.  Crate 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.
 *
 * However, if you have executed another commercial license agreement
 * with Crate these terms will supersede the license and you may use the
 * software solely pursuant to the terms of the relevant commercial agreement.
 */

package io.crate.expression.scalar;

import io.crate.data.Input;
import io.crate.expression.symbol.Function;
import io.crate.expression.symbol.Literal;
import io.crate.expression.symbol.Symbol;
import io.crate.metadata.NodeContext;
import io.crate.metadata.Scalar;
import io.crate.metadata.TransactionContext;
import io.crate.metadata.functions.Signature;
import io.crate.types.DataTypes;

public class ConcatWsFunction extends Scalar<String, String> {

    public static final String NAME = "concat_ws";

    public static void register(ScalarFunctionModule module) {
        module.register(
            Signature.scalar(
                NAME,
                DataTypes.STRING.getTypeSignature(),
                DataTypes.STRING.getTypeSignature()
            ).withVariableArity(),
            ConcatWsFunction::new
        );
    }

    private final Signature signature;
    private final Signature boundSignature;

    ConcatWsFunction(Signature signature, Signature boundSignature) {
        this.signature = signature;
        this.boundSignature = boundSignature;
    }

    @Override
    public String evaluate(TransactionContext txnCtx, NodeContext nodeCtx, Input[] args) {

        String separator = (String) args[0].value();
        if (separator == null) {
            return null;
        }

        StringBuilder sb = new StringBuilder();

        boolean firstNonNullProcessed = false;
        for (int i = 1; i < args.length; i++) {
            String value = (String) args[i].value();
            if (value != null) {
                if (!firstNonNullProcessed) {
                    firstNonNullProcessed = true;
                    sb.append(value);
                } else {
                    sb.append(separator).append(value);
                }
            }
        }
        return sb.toString();
    }

    @Override
    public Signature signature() {
        return signature;
    }

    @Override
    public Signature boundSignature() {
        return boundSignature;
    }

    @Override
    public Symbol normalizeSymbol(Function function, TransactionContext txnCtx, NodeContext nodeCtx) {
        if (anyNonLiterals(function.arguments())) {
            return function;
        }
        Input[] inputs = new Input[function.arguments().size()];
        for (int i = 0; i < function.arguments().size(); i++) {
            inputs[i] = ((Input) function.arguments().get(i));
        }
        //noinspection unchecked
        return Literal.ofUnchecked(boundSignature.getReturnType().createType(), evaluate(txnCtx, nodeCtx, inputs));
    }
}

@@ -1075,137 +1075,8 @@
 ut;%0A
-import io.crate.expression.symbol.Function;%0Aimport io.crate.expression.symbol.Literal;%0Aimport io.crate.expression.symbol.Symbol;%0A
 impo
@@ -1101,32 +1101,32 @@
 ta.NodeContext;%0A
+
 import io.crate.
@@ -1964,32 +1964,49 @@
 %0A%0A    @Override%0A
+    @SafeVarargs%0A
     public Strin
@@ -2000,16 +2000,22 @@
  public 
+final 
 String e
@@ -2075,18 +2075,28 @@
 x, Input
-%5B%5D
+%3CString%3E ...
  args) %7B
@@ -2096,17 +2096,16 @@
 args) %7B%0A
-%0A
         
@@ -2122,25 +2122,16 @@
 arator =
- (String)
  args%5B0%5D
@@ -2861,32 +2861,32 @@
 ndSignature() %7B%0A
+
         return b
@@ -2909,573 +2909,7 @@
    %7D
-%0A%0A    @Override%0A    public Symbol normalizeSymbol(Function function, TransactionContext txnCtx, NodeContext nodeCtx) %7B%0A        if (anyNonLiterals(function.arguments())) %7B%0A            return function;%0A        %7D%0A        Input%5B%5D inputs = new Input%5Bfunction.arguments().size()%5D;%0A        for (int i = 0; i %3C function.arguments().size(); i++) %7B%0A            inputs%5Bi%5D = ((Input) function.arguments().get(i));%0A        %7D%0A        //noinspection unchecked%0A        return Literal.ofUnchecked(boundSignature.getReturnType().createType(), evaluate(txnCtx, nodeCtx, inputs));%0A    %7D
 %0A%7D%0A

Remove normalizeSymbol override from ConcatWsFunction