/*
 * 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 com.facebook.presto.metadata;

import com.facebook.presto.operator.scalar.ScalarFunctionImplementation;
import com.facebook.presto.spi.type.TypeManager;
import com.facebook.presto.spi.type.TypeSignature;
import com.google.common.collect.ImmutableList;

import java.lang.invoke.MethodHandle;
import java.util.List;
import java.util.Optional;

import static com.facebook.presto.metadata.FunctionRegistry.mangleOperatorName;
import static java.util.Objects.requireNonNull;

public abstract class SqlOperator
        extends SqlScalarFunction
{
    public static SqlOperator create(
            OperatorType operatorType,
            List<TypeVariableConstraint> typeVariableConstraints,
            List<LongVariableConstraint> longVariableConstraints,
            List<TypeSignature> argumentTypes,
            TypeSignature returnType,
            MethodHandle methodHandle,
            Optional<MethodHandle> instanceFactory,
            boolean nullable,
            List<Boolean> nullableArguments)
    {
        // TODO This should take Signature!
        return new SimpleSqlOperator(operatorType,
                typeVariableConstraints,
                longVariableConstraints,
                argumentTypes,
                returnType,
                methodHandle,
                instanceFactory,
                nullable,
                nullableArguments);
    }

    protected SqlOperator(OperatorType operatorType, List<TypeVariableConstraint> typeVariableConstraints, List<LongVariableConstraint> longVariableConstraints, TypeSignature returnType, List<TypeSignature> argumentTypes)
    {
        // TODO This should take Signature!
        super(new Signature(
                mangleOperatorName(operatorType),
                FunctionKind.SCALAR,
                typeVariableConstraints,
                longVariableConstraints,
                returnType,
                argumentTypes,
                false));
    }

    @Override
    public final boolean isHidden()
    {
        return true;
    }

    @Override
    public final boolean isDeterministic()
    {
        return true;
    }

    @Override
    public final String getDescription()
    {
        // Operators are internal, and don't need a description
        return null;
    }

    public static class SimpleSqlOperator
            extends SqlOperator
    {
        private final MethodHandle methodHandle;
        private final Optional<MethodHandle> instanceFactory;
        private final boolean nullable;
        private final List<Boolean> nullableArguments;

        public SimpleSqlOperator(
                OperatorType operatorType,
                List<TypeVariableConstraint> typeVariableConstraints,
                List<LongVariableConstraint> longVariableConstraints,
                List<TypeSignature> argumentTypes,
                TypeSignature returnType,
                MethodHandle methodHandle,
                Optional<MethodHandle> instanceFactory,
                boolean nullable,
                List<Boolean> nullableArguments)
        {
            // TODO This should take Signature!
            super(operatorType, typeVariableConstraints, longVariableConstraints, returnType, argumentTypes);
            this.methodHandle = requireNonNull(methodHandle, "methodHandle is null");
            this.instanceFactory = requireNonNull(instanceFactory, "instanceFactory is null");
            this.nullable = nullable;
            this.nullableArguments = ImmutableList.copyOf(requireNonNull(nullableArguments, "nullableArguments is null"));
        }

        @Override
        public ScalarFunctionImplementation specialize(BoundVariables boundVariables, int arity, TypeManager typeManager, FunctionRegistry functionRegistry)
        {
            return new ScalarFunctionImplementation(nullable, nullableArguments, methodHandle, instanceFactory, isDeterministic());
        }
    }
}

@@ -625,289 +625,54 @@
 sto.
-operator.scalar.ScalarFunctionImplementation;%0Aimport com.facebook.presto.spi.type.TypeManager;%0Aimport com.facebook.presto.spi.type.TypeSignature;%0Aimport com.google.common.collect.ImmutableList;%0A%0Aimport java.lang.invoke.MethodHandle;%0Aimport java.util.List;%0Aimport java.util.Optional
+spi.type.TypeSignature;%0A%0Aimport java.util.List
 ;%0A%0Ai
@@ -753,56 +753,8 @@
 ame;
-%0Aimport static java.util.Objects.requireNonNull;
 %0A%0Apu
@@ -825,842 +825,8 @@
 n%0A%7B%0A
-    public static SqlOperator create(%0A            OperatorType operatorType,%0A            List%3CTypeVariableConstraint%3E typeVariableConstraints,%0A            List%3CLongVariableConstraint%3E longVariableConstraints,%0A            List%3CTypeSignature%3E argumentTypes,%0A            TypeSignature returnType,%0A            MethodHandle methodHandle,%0A            Optional%3CMethodHandle%3E instanceFactory,%0A            boolean nullable,%0A            List%3CBoolean%3E nullableArguments)%0A    %7B%0A        // TODO This should take Signature!%0A        return new SimpleSqlOperator(operatorType,%0A                typeVariableConstraints,%0A                longVariableConstraints,%0A                argumentTypes,%0A                returnType,%0A                methodHandle,%0A                instanceFactory,%0A                nullable,%0A                nullableArguments);%0A    %7D%0A%0A
     
@@ -1712,1641 +1712,7 @@
    %7D
-%0A%0A    public static class SimpleSqlOperator%0A            extends SqlOperator%0A    %7B%0A        private final MethodHandle methodHandle;%0A        private final Optional%3CMethodHandle%3E instanceFactory;%0A        private final boolean nullable;%0A        private final List%3CBoolean%3E nullableArguments;%0A%0A        public SimpleSqlOperator(%0A                OperatorType operatorType,%0A                List%3CTypeVariableConstraint%3E typeVariableConstraints,%0A                List%3CLongVariableConstraint%3E longVariableConstraints,%0A                List%3CTypeSignature%3E argumentTypes,%0A                TypeSignature returnType,%0A                MethodHandle methodHandle,%0A                Optional%3CMethodHandle%3E instanceFactory,%0A                boolean nullable,%0A                List%3CBoolean%3E nullableArguments)%0A        %7B%0A            // TODO This should take Signature!%0A            super(operatorType, typeVariableConstraints, longVariableConstraints, returnType, argumentTypes);%0A            this.methodHandle = requireNonNull(methodHandle, %22methodHandle is null%22);%0A            this.instanceFactory = requireNonNull(instanceFactory, %22instanceFactory is null%22);%0A            this.nullable = nullable;%0A            this.nullableArguments = ImmutableList.copyOf(requireNonNull(nullableArguments, %22nullableArguments is null%22));%0A        %7D%0A%0A        @Override%0A        public ScalarFunctionImplementation specialize(BoundVariables boundVariables, int arity, TypeManager typeManager, FunctionRegistry functionRegistry)%0A        %7B%0A            return new ScalarFunctionImplementation(nullable, nullableArguments, methodHandle, instanceFactory, isDeterministic());%0A        %7D%0A    %7D
 %0A%7D%0A

Remove unused code from SqlOperator