/*
 * 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.
 */

package org.apache.wayang.flink.operators;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.apache.flink.api.common.functions.CoGroupFunction;
import org.apache.flink.api.java.DataSet;
import org.apache.flink.api.java.functions.KeySelector;
import org.apache.flink.util.Collector;
import org.apache.wayang.basic.data.Tuple2;
import org.apache.wayang.basic.operators.CoGroupOperator;
import org.apache.wayang.core.function.FunctionDescriptor;
import org.apache.wayang.core.function.TransformationDescriptor;
import org.apache.wayang.core.optimizer.OptimizationContext;
import org.apache.wayang.core.plan.wayangplan.ExecutionOperator;
import org.apache.wayang.core.platform.ChannelDescriptor;
import org.apache.wayang.core.platform.ChannelInstance;
import org.apache.wayang.core.platform.lineage.ExecutionLineageNode;
import org.apache.wayang.core.types.DataSetType;
import org.apache.wayang.core.util.ReflectionUtils;
import org.apache.wayang.core.util.Tuple;
import org.apache.wayang.flink.channels.DataSetChannel;
import org.apache.wayang.flink.compiler.FunctionCompiler;
import org.apache.wayang.flink.execution.FlinkExecutor;

/**
 * Flink implementation of the {@link CoGroupOperator}.
 */
public class FlinkCoGroupOperator<InputType0, InputType1, TypeKey>
        extends CoGroupOperator<InputType0, InputType1, TypeKey>
        implements FlinkExecutionOperator {
    /**
     * @see CoGroupOperator#CoGroupOperator(FunctionDescriptor.SerializableFunction, FunctionDescriptor.SerializableFunction, Class, Class, Class)
     */
    public FlinkCoGroupOperator(FunctionDescriptor.SerializableFunction<InputType0, TypeKey> keyExtractor0,
                                FunctionDescriptor.SerializableFunction<InputType1, TypeKey> keyExtractor1,
                                Class<InputType0> input0Class,
                                Class<InputType1> input1Class,
                                Class<TypeKey> keyClass) {
        super(keyExtractor0, keyExtractor1, input0Class, input1Class, keyClass);
    }

    /**
     * @see CoGroupOperator#CoGroupOperator(TransformationDescriptor, TransformationDescriptor)
     */
    public FlinkCoGroupOperator(TransformationDescriptor<InputType0, TypeKey> keyDescriptor0,
                                TransformationDescriptor<InputType1, TypeKey> keyDescriptor1) {
        super(keyDescriptor0, keyDescriptor1);
    }

    /**
     * @see CoGroupOperator#CoGroupOperator(TransformationDescriptor, TransformationDescriptor, DataSetType, DataSetType)
     */
    public FlinkCoGroupOperator(TransformationDescriptor<InputType0, TypeKey> keyDescriptor0,
                                TransformationDescriptor<InputType1, TypeKey> keyDescriptor1,
                                DataSetType<InputType0> inputType0,
                                DataSetType<InputType1> inputType1) {
        super(keyDescriptor0, keyDescriptor1, inputType0, inputType1);
    }

    /**
     * @see CoGroupOperator#CoGroupOperator(CoGroupOperator)
     */
    public FlinkCoGroupOperator(CoGroupOperator<InputType0, InputType1, TypeKey> that) {
        super(that);
    }

    @Override
    public Tuple<Collection<ExecutionLineageNode>, Collection<ChannelInstance>> evaluate(
            ChannelInstance[] inputs,
            ChannelInstance[] outputs,
            FlinkExecutor flinkExecutor,
            OptimizationContext.OperatorContext operatorContext) {
        assert inputs.length == this.getNumInputs();
        assert outputs.length == this.getNumOutputs();

        final DataSetChannel.Instance input0 = (DataSetChannel.Instance) inputs[0];
        final DataSetChannel.Instance input1 = (DataSetChannel.Instance) inputs[1];
        final DataSetChannel.Instance output = (DataSetChannel.Instance) outputs[0];

        final DataSet<InputType0> datasetInput0 = input0.provideDataSet();
        final DataSet<InputType1> datasetInput1 = input1.provideDataSet();

        FunctionCompiler compiler = flinkExecutor.getCompiler();

        KeySelector<InputType0, TypeKey> function0 = compiler.compileKeySelector(this.keyDescriptor0);
        KeySelector<InputType1, TypeKey> function1 = compiler.compileKeySelector(this.keyDescriptor1);


        final DataSet<Tuple2<Iterable<InputType0>, Iterable<InputType1>>> datasetOutput = datasetInput0.coGroup(datasetInput1)
        .where(
            function0
        ).equalTo(
             function1
        ).with(
            new CoGroupFunction<InputType0, InputType1, Tuple2<Iterable<InputType0>, Iterable<InputType1>>>() {
                @Override
                public void coGroup (
                            Iterable<InputType0> iterable,
                            Iterable<InputType1> iterable1,
                            Collector< Tuple2<Iterable<InputType0>, Iterable<InputType1>> > collector
                ){
                    List<InputType0> list0 = new ArrayList<>();
                    List<InputType1> list1 = new ArrayList<>();
                    iterable.forEach(list0::add);
                    iterable1.forEach(list1::add);
                    collector.collect( new Tuple2<>(list0, list1));
                }
        }).returns(ReflectionUtils.specify(Tuple2.class));

        output.accept(datasetOutput, flinkExecutor);

        return ExecutionOperator.modelLazyExecution(inputs, outputs, operatorContext);
    }

    @Override
    protected ExecutionOperator createCopy() {
        return new FlinkCoGroupOperator<>(this);
    }

    public String getLoadProfileEstimatorConfigurationTypeKey() {
        return "wayang.flink.cogroup.load";
    }

    @Override
    public List<ChannelDescriptor> getSupportedInputChannels(int index) {
        assert index <= this.getNumInputs() || (index == 0 && this.getNumInputs() == 0);
        return Arrays.asList(DataSetChannel.DESCRIPTOR, DataSetChannel.DESCRIPTOR_MANY);
    }

    @Override
    public List<ChannelDescriptor> getSupportedOutputChannels(int index) {
        assert index <= this.getNumOutputs() || (index == 0 && this.getNumOutputs() == 0);
        return Collections.singletonList(DataSetChannel.DESCRIPTOR);
    }

    @Override
    public boolean containsAction() {
        return false;
    }
    
}
