/*
 * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
 *
 * WSO2 Inc. 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 io.siddhi.core.query.selector.attribute.aggregator;

import io.siddhi.annotation.Example;
import io.siddhi.annotation.Extension;
import io.siddhi.annotation.ParameterOverload;
import io.siddhi.annotation.ReturnAttribute;
import io.siddhi.annotation.util.DataType;
import io.siddhi.core.config.SiddhiQueryContext;
import io.siddhi.core.executor.ExpressionExecutor;
import io.siddhi.core.query.processor.ProcessingMode;
import io.siddhi.core.util.config.ConfigReader;
import io.siddhi.core.util.snapshot.state.State;
import io.siddhi.core.util.snapshot.state.StateFactory;
import io.siddhi.query.api.definition.Attribute;

import java.util.HashMap;
import java.util.Map;

/**
 * {@link AttributeAggregatorExecutor} to calculate count.
 */
@Extension(
        name = "count",
        namespace = "",
        description = "Returns the count of all the events.",
        parameters = {},
        parameterOverloads = {
                @ParameterOverload()
        },
        returnAttributes = @ReturnAttribute(
                description = "Returns the event count as a long.",
                type = {DataType.LONG}),
        examples = @Example(
                syntax = "from fooStream#window.timeBatch(10 sec)\n" +
                        "select count() as count\n" +
                        "insert into barStream;",
                description = "This will return the count of all the events for time batch in 10 seconds."
        )
)
public class CountAttributeAggregatorExecutor
        extends AttributeAggregatorExecutor<CountAttributeAggregatorExecutor.AggregatorState> {

    private static Attribute.Type type = Attribute.Type.LONG;

    /**
     * The initialization method for FunctionExecutor
     *
     * @param attributeExpressionExecutors are the executors of each attributes in the function
     * @param processingMode               query processing mode
     * @param outputExpectsExpiredEvents   is expired events sent as output
     * @param configReader                 this hold the {@link CountAttributeAggregatorExecutor} configuration reader.
     * @param siddhiQueryContext           Siddhi query runtime context
     */
    @Override
    protected StateFactory<AggregatorState> init(ExpressionExecutor[] attributeExpressionExecutors,
                                                 ProcessingMode processingMode,
                                                 boolean outputExpectsExpiredEvents,
                                                 ConfigReader configReader,
                                                 SiddhiQueryContext siddhiQueryContext) {
        return () -> new AggregatorState();

    }

    public Attribute.Type getReturnType() {
        return type;
    }

    @Override
    public Object processAdd(Object data, AggregatorState state) {
        state.count++;
        return state.count;
    }

    @Override
    public Object processAdd(Object[] data, AggregatorState state) {
        state.count++;
        return state.count;
    }

    @Override
    public Object processRemove(Object data, AggregatorState state) {
        state.count--;
        return state.count;
    }

    @Override
    public Object processRemove(Object[] data, AggregatorState state) {
        state.count--;
        return state.count;
    }

    @Override
    public Object reset(AggregatorState state) {
        state.count = 0L;
        return state.count;
    }


    class AggregatorState extends State {
        private long count = 0L;

        @Override
        public boolean canDestroy() {
            return count == 0L;
        }

        @Override
        public Map<String, Object> snapshot() {
            Map<String, Object> state = new HashMap<>();
            state.put("Count", count);
            return state;
        }

        @Override
        public void restore(Map<String, Object> state) {
            count = (long) state.get("Count");
        }
    }
}

@@ -804,16 +804,55 @@
 ension;%0A
+import io.siddhi.annotation.Parameter;%0A
 import i
@@ -1595,16 +1595,487 @@
 ters = %7B
+%0A                @Parameter(name = %22arg%22,%0A                        description = %22This function accepts one parameter. %22 +%0A                                %22It can belong to any one of the available types.%22,%0A                        type = %7BDataType.INT, DataType.LONG, DataType.DOUBLE, DataType.FLOAT,%0A                                DataType.STRING, DataType.BOOL, DataType.OBJECT%7D,%0A                        dynamic = true,%0A                        optional = true)%0A        
 %7D,%0A     
@@ -2136,16 +2136,78 @@
 erload()
+,%0A                @ParameterOverload(parameterNames = %7B%22arg%22%7D)
 %0A       

Fix the CountAttributeAggregator for backward compatibility