package com.yahoo.labs.samoa.learners.classifiers.rules.distributed;

/*
 * #%L
 * SAMOA
 * %%
 * Copyright (C) 2013 - 2014 Yahoo! Inc.
 * %%
 * 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.
 * #L%
 */

import com.yahoo.labs.samoa.core.ContentEvent;
import com.yahoo.labs.samoa.core.Processor;
import com.yahoo.labs.samoa.instances.Instance;
import com.yahoo.labs.samoa.instances.Instances;
import com.yahoo.labs.samoa.learners.InstanceContentEvent;
import com.yahoo.labs.samoa.learners.ResultContentEvent;
import com.yahoo.labs.samoa.learners.classifiers.rules.common.ActiveRule;
import com.yahoo.labs.samoa.learners.classifiers.rules.common.LearningRule;
import com.yahoo.labs.samoa.learners.classifiers.rules.common.PassiveRule;
import com.yahoo.labs.samoa.moa.classifiers.rules.core.voting.ErrorWeightedVote;
import com.yahoo.labs.samoa.moa.classifiers.rules.core.voting.InverseErrorWeightedVote;
import com.yahoo.labs.samoa.moa.classifiers.rules.core.voting.UniformWeightedVote;
import com.yahoo.labs.samoa.topology.Stream;
import java.util.LinkedList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Model Aggregator Processor (HAMR).
 * 
 * @author Anh Thu Vu
 * 
 */
public class AMRRuleSetProcessor implements Processor {

  /**
	 * 
	 */
  private static final long serialVersionUID = -6544096255649379334L;
  private static final Logger logger = LoggerFactory.getLogger(AMRRuleSetProcessor.class);

  private int processorId;

  // Rules & default rule
  protected transient List<PassiveRule> ruleSet;

  // SAMOA Stream
  private Stream statisticsStream;
  private Stream resultStream;
  private Stream defaultRuleStream;

  // Options
  protected boolean noAnomalyDetection;
  protected double multivariateAnomalyProbabilityThreshold;
  protected double univariateAnomalyprobabilityThreshold;
  protected int anomalyNumInstThreshold;

  protected boolean unorderedRules;

  protected int voteType;

  /*
   * Constructor
   */
  public AMRRuleSetProcessor(Builder builder) {

    this.noAnomalyDetection = builder.noAnomalyDetection;
    this.multivariateAnomalyProbabilityThreshold = builder.multivariateAnomalyProbabilityThreshold;
    this.univariateAnomalyprobabilityThreshold = builder.univariateAnomalyprobabilityThreshold;
    this.anomalyNumInstThreshold = builder.anomalyNumInstThreshold;
    this.unorderedRules = builder.unorderedRules;

    this.voteType = builder.voteType;
  }

  /*
   * (non-Javadoc)
   * 
   * @see com.yahoo.labs.samoa.core.Processor#process(com.yahoo.labs.samoa.core.
   * ContentEvent)
   */
  @Override
  public boolean process(ContentEvent event) {
    if (event instanceof InstanceContentEvent) {
      this.processInstanceEvent((InstanceContentEvent) event);
    }
    else if (event instanceof PredicateContentEvent) {
      PredicateContentEvent pce = (PredicateContentEvent) event;
      if (pce.getRuleSplitNode() == null) {
        this.updateLearningNode(pce);
      }
      else {
        this.updateRuleSplitNode(pce);
      }
    }
    else if (event instanceof RuleContentEvent) {
      RuleContentEvent rce = (RuleContentEvent) event;
      if (rce.isRemoving()) {
        this.removeRule(rce.getRuleNumberID());
      }
      else {
        addRule(rce.getRule());
      }
    }
    return true;
  }

  private void processInstanceEvent(InstanceContentEvent instanceEvent) {
    Instance instance = instanceEvent.getInstance();
    boolean predictionCovered = false;
    boolean trainingCovered = false;
    boolean continuePrediction = instanceEvent.isTesting();
    boolean continueTraining = instanceEvent.isTraining();

    ErrorWeightedVote errorWeightedVote = newErrorWeightedVote();
    for (PassiveRule aRuleSet : this.ruleSet) {
      if (!continuePrediction && !continueTraining)
        break;

      if (aRuleSet.isCovering(instance)) {
        predictionCovered = true;

        if (continuePrediction) {
          double[] vote = aRuleSet.getPrediction(instance);
          double error = aRuleSet.getCurrentError();
          errorWeightedVote.addVote(vote, error);
          if (!this.unorderedRules)
            continuePrediction = false;
        }

        if (continueTraining) {
          if (!isAnomaly(instance, aRuleSet)) {
            trainingCovered = true;
            aRuleSet.updateStatistics(instance);

            // Send instance to statistics PIs
            sendInstanceToRule(instance, aRuleSet.getRuleNumberID());

            if (!this.unorderedRules)
              continueTraining = false;
          }
        }
      }
    }

    if (predictionCovered) {
      // Combined prediction
      ResultContentEvent rce = newResultContentEvent(errorWeightedVote.computeWeightedVote(), instanceEvent);
      resultStream.put(rce);
    }

    boolean defaultPrediction = instanceEvent.isTesting() && !predictionCovered;
    boolean defaultTraining = instanceEvent.isTraining() && !trainingCovered;
    if (defaultPrediction || defaultTraining) {
      instanceEvent.setTesting(defaultPrediction);
      instanceEvent.setTraining(defaultTraining);
      this.defaultRuleStream.put(instanceEvent);
    }
  }

  private ResultContentEvent newResultContentEvent(double[] prediction, InstanceContentEvent inEvent) {
    ResultContentEvent rce = new ResultContentEvent(inEvent.getInstanceIndex(), inEvent.getInstance(),
        inEvent.getClassId(), prediction, inEvent.isLastEvent());
    rce.setClassifierIndex(this.processorId);
    rce.setEvaluationIndex(inEvent.getEvaluationIndex());
    return rce;
  }

  public ErrorWeightedVote newErrorWeightedVote() {
    // TODO: do a reset instead of init a new object
    if (voteType == 1)
      return new UniformWeightedVote();
    return new InverseErrorWeightedVote();
  }

  /**
   * Method to verify if the instance is an anomaly.
   * 
   * @param instance
   * @param rule
   * @return
   */
  private boolean isAnomaly(Instance instance, LearningRule rule) {
    // AMRUles is equipped with anomaly detection. If on, compute the anomaly
    // value.
    boolean isAnomaly = false;
    if (!this.noAnomalyDetection) {
      if (rule.getInstancesSeen() >= this.anomalyNumInstThreshold) {
        isAnomaly = rule.isAnomaly(instance,
            this.univariateAnomalyprobabilityThreshold,
            this.multivariateAnomalyProbabilityThreshold,
            this.anomalyNumInstThreshold);
      }
    }
    return isAnomaly;
  }

  /*
   * Add predicate/RuleSplitNode for a rule
   */
  private void updateRuleSplitNode(PredicateContentEvent pce) {
    int ruleID = pce.getRuleNumberID();
    for (PassiveRule rule : ruleSet) {
      if (rule.getRuleNumberID() == ruleID) {
        rule.nodeListAdd(pce.getRuleSplitNode());
        rule.setLearningNode(pce.getLearningNode());
      }
    }
  }

  private void updateLearningNode(PredicateContentEvent pce) {
    int ruleID = pce.getRuleNumberID();
    for (PassiveRule rule : ruleSet) {
      if (rule.getRuleNumberID() == ruleID) {
        rule.setLearningNode(pce.getLearningNode());
      }
    }
  }

  /*
   * Add new rule/Remove rule
   */
  private boolean addRule(ActiveRule rule) {
    this.ruleSet.add(new PassiveRule(rule));
    return true;
  }

  private void removeRule(int ruleID) {
    for (PassiveRule rule : ruleSet) {
      if (rule.getRuleNumberID() == ruleID) {
        ruleSet.remove(rule);
        break;
      }
    }
  }

  @Override
  public void onCreate(int id) {
    this.processorId = id;
    this.ruleSet = new LinkedList<PassiveRule>();

  }

  /*
   * Clone processor
   */
  @Override
  public Processor newProcessor(Processor p) {
    AMRRuleSetProcessor oldProcessor = (AMRRuleSetProcessor) p;
    Builder builder = new Builder(oldProcessor);
    AMRRuleSetProcessor newProcessor = builder.build();
    newProcessor.resultStream = oldProcessor.resultStream;
    newProcessor.statisticsStream = oldProcessor.statisticsStream;
    newProcessor.defaultRuleStream = oldProcessor.defaultRuleStream;
    return newProcessor;
  }

  /*
   * Send events
   */
  private void sendInstanceToRule(Instance instance, int ruleID) {
    AssignmentContentEvent ace = new AssignmentContentEvent(ruleID, instance);
    this.statisticsStream.put(ace);
  }

  /*
   * Output streams
   */
  public void setStatisticsStream(Stream statisticsStream) {
    this.statisticsStream = statisticsStream;
  }

  public Stream getStatisticsStream() {
    return this.statisticsStream;
  }

  public void setResultStream(Stream resultStream) {
    this.resultStream = resultStream;
  }

  public Stream getResultStream() {
    return this.resultStream;
  }

  public Stream getDefaultRuleStream() {
    return this.defaultRuleStream;
  }

  public void setDefaultRuleStream(Stream defaultRuleStream) {
    this.defaultRuleStream = defaultRuleStream;
  }

  /*
   * Builder
   */
  public static class Builder {
    private boolean noAnomalyDetection;
    private double multivariateAnomalyProbabilityThreshold;
    private double univariateAnomalyprobabilityThreshold;
    private int anomalyNumInstThreshold;

    private boolean unorderedRules;

    // private FIMTDDNumericAttributeClassLimitObserver numericObserver;
    private int voteType;

    private Instances dataset;

    public Builder(Instances dataset) {
      this.dataset = dataset;
    }

    public Builder(AMRRuleSetProcessor processor) {

      this.noAnomalyDetection = processor.noAnomalyDetection;
      this.multivariateAnomalyProbabilityThreshold = processor.multivariateAnomalyProbabilityThreshold;
      this.univariateAnomalyprobabilityThreshold = processor.univariateAnomalyprobabilityThreshold;
      this.anomalyNumInstThreshold = processor.anomalyNumInstThreshold;
      this.unorderedRules = processor.unorderedRules;

      this.voteType = processor.voteType;
    }

    public Builder noAnomalyDetection(boolean noAnomalyDetection) {
      this.noAnomalyDetection = noAnomalyDetection;
      return this;
    }

    public Builder multivariateAnomalyProbabilityThreshold(double mAnomalyThreshold) {
      this.multivariateAnomalyProbabilityThreshold = mAnomalyThreshold;
      return this;
    }

    public Builder univariateAnomalyProbabilityThreshold(double uAnomalyThreshold) {
      this.univariateAnomalyprobabilityThreshold = uAnomalyThreshold;
      return this;
    }

    public Builder anomalyNumberOfInstancesThreshold(int anomalyNumInstThreshold) {
      this.anomalyNumInstThreshold = anomalyNumInstThreshold;
      return this;
    }

    public Builder unorderedRules(boolean unorderedRules) {
      this.unorderedRules = unorderedRules;
      return this;
    }

    public Builder voteType(int voteType) {
      this.voteType = voteType;
      return this;
    }

    public AMRRuleSetProcessor build() {
      return new AMRRuleSetProcessor(this);
    }
  }

}
