/*
 * Copyright 2016 PantherCode
 *
 * 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.panthercode.arctic.core.processing.modules.impl;

import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.panthercode.arctic.core.helper.identity.annotation.IdentityInfo;
import org.panthercode.arctic.core.helper.version.annotation.VersionInfo;
import org.panthercode.arctic.core.processing.modules.Module;
import org.panthercode.arctic.core.processing.modules.options.CounterOptions;
import org.panthercode.arctic.core.settings.context.Context;

//TODO: create Builder class
//TODO: update documentation

/**
 * The Counter class repeats the module's functionality until a numeric limit is reached or (if canAbort flag is set)
 * until the module finished successfully.
 */
@IdentityInfo(name = "Standard Counter", group = "Counter Module")
@VersionInfo(major = 1)
public class Counter extends Loop {

    /**
     * actual round
     */
    private int actualCount = 0;

    /**
     * Constructor
     *
     * @param module module for processing
     * @throws NullPointerException
     */
    public Counter(Module module)
            throws NullPointerException {
        this(module, new CounterOptions());
    }

    /**
     * Constructor
     *
     * @param module module to processing
     * @throws NullPointerException
     */
    public Counter(Module module,
                   CounterOptions options)
            throws NullPointerException {
        this(module, options, null);
    }

    /**
     * Constructor
     *
     * @param module
     * @param context
     * @throws NullPointerException
     */
    public Counter(Module module,
                   CounterOptions options,
                   Context context)
            throws NullPointerException {
        super(module, options, context);

        //this.setCount(count);
    }

    /**
     * Copy Constructor
     *
     * @param counter object to copy
     */
    public Counter(Counter counter) {
        super(counter.module.copy(),
                new CounterOptions(counter.getCount(),
                        counter.getDelayTime(),
                        counter.isIgnoreExceptions(),
                        counter.canQuit()),
                counter.getContext());
    }


    /**
     * Return the actual maximal number of repeats.
     *
     * @return Return the actual maximal number of repeats.
     */
    public int getCount() {
        return ((CounterOptions) this.options).getCount();
    }

    /**
     * Set a new number as maximum for repeats.
     *
     * @param count new maximal number of repeats
     * @throws IllegalArgumentException Is thrown if value is zero or less.
     */
    public synchronized void setCount(final int count) {
        ((CounterOptions) this.options).setCount(count);
    }

    /**
     * Returns the number repeats have done until starting the process.
     *
     * @return Returns the actual number of repeats have done or zero if process state is not "Running".
     */
    public int actualCount() {
        return (this.isRunning()) ? this.actualCount : 0;
    }


    @Override
    public Counter copy()
            throws UnsupportedOperationException {
        return new Counter(this);
    }

    /**
     * Returns a hash code value of this object.
     *
     * @return Returns a hash code value of this object.
     */
    @Override
    public int hashCode() {
        return Math.abs(new HashCodeBuilder()
                .append(super.hashCode())
                .append(this.getCount())
                .toHashCode());
    }

    /**
     * Checks if this object is equals to another one.
     *
     * @param obj other object for comparison
     * @return Returns <code>true</code> if both objects are equal; Otherwise <tt>false</tt>.
     */
    @Override
    public boolean equals(final Object obj) {
        if (obj == this) {
            return true;
        }

        if (!(obj instanceof Loop)) {
            return false;
        }

        Counter counter = (Counter) obj;
        return super.equals(counter) &&
                this.canQuit() == counter.canQuit() &&
                this.getCount() == counter.getCount();
    }

    @Override
    protected void loop() {
        this.actualCount = 0;
        int loop;

        for (loop = 0;
             loop < this.getCount() && this.isRunning() && this.step();
             loop++, this.actualCount = loop)
            ;
    }
}


@@ -1066,37 +1066,8 @@
 t;%0A%0A
-//TODO: create Builder class%0A
 //TO
@@ -2310,41 +2310,8 @@
 xt);
-%0A%0A        //this.setCount(count);
 %0A   
@@ -3200,24 +3200,60 @@
 nt count) %7B%0A
+        if (this.canModify()) %7B%0A    
         ((Co
@@ -3293,24 +3293,34 @@
 unt(count);%0A
+        %7D%0A
     %7D%0A%0A    /
@@ -4729,17 +4729,27 @@
 ed void 
-l
+initialiseL
 oop() %7B%0A
@@ -4786,63 +4786,96 @@
     
+%7D%0A%0A
     
-int loop;%0A%0A        for (loop = 0;%0A             loop
+@Override%0A    protected boolean loopCondition() %7B%0A        return this.actualCount
  %3C t
@@ -4912,83 +4912,90 @@
 ng()
- && this.step()
 ;%0A    
+%7D%0A%0A
     
-     loop++, this.actualCount = loop)%0A            
+@Override%0A    protected void afterLoop() %7B%0A        this.actualCount++
 ;%0A  

modify implementation