/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package motif;

import data.IHanson;
import data.IMotif;
import data.IPhrase;
import data.MotifType;
import java.util.ArrayList;
import java.util.HashMap;

/**
 *
 * @author smuRf
 */
public class MotifDetection {
    private static int MIN_MOTIF_LENGTH = 3;
    private static int MAX_MOTIF_LENGTH = 7;
    private static int ALLOWED_INTERVAL_VARIATION = 1;
    private static int MAX_MOTIF_EXTENSION = 3;
    private HashMap<MotifType, ArrayList<IMotif>> detectedMotifs = new HashMap();
    
    public MotifDetection(int minL, int maxL, int intervalVariation, int maxMotifExtension)
    {
        MIN_MOTIF_LENGTH = minL;
        MAX_MOTIF_LENGTH = maxL;
        ALLOWED_INTERVAL_VARIATION = intervalVariation;
        MAX_MOTIF_EXTENSION = maxMotifExtension;
    }
    
    public HashMap<MotifType, ArrayList<IMotif>> detect(IPhrase iPhrase)
    {
        HashMap<Double [], Integer> intervalPatterns = getPotentialBaseMotifs(iPhrase);
        ArrayList<IMotif> repetitionMotifs = new ArrayList();        
        ArrayList<IMotif> variationMotifs = new ArrayList();        
        ArrayList<IMotif> rhythmicMotifs = new ArrayList();      
        
        RepetitionMotifDectorHanson repDetector = new RepetitionMotifDectorHanson();
        VariationMotifDetectorHanson varDetector = new VariationMotifDetectorHanson();
        RhythmicMotifDetectorHanson rhyDetector = new RhythmicMotifDetectorHanson();
        
        varDetector.setAllowedIntervalVariation(ALLOWED_INTERVAL_VARIATION);
        rhyDetector.setMaxMotifExtension(MAX_MOTIF_EXTENSION);
        
        new PatternMatcher(iPhrase.getPostHansonValues().getIntervals(), iPhrase.getPreHansonValues().getIntervals(), iPhrase);
        
        detectedMotifs.clear();
        repetitionMotifs.addAll(PatternMatcher.match(iPhrase.getPostHansonValues().getIntervals(), iPhrase.getPreHansonValues().getIntervals(), intervalPatterns, iPhrase, repDetector));
        variationMotifs.addAll(PatternMatcher.match(iPhrase.getPostHansonValues().getIntervals(), iPhrase.getPreHansonValues().getIntervals(), intervalPatterns, iPhrase, varDetector));
        rhythmicMotifs.addAll(PatternMatcher.match(iPhrase.getPostHansonValues().getIntervals(), iPhrase.getPreHansonValues().getIntervals(), intervalPatterns, iPhrase, rhyDetector));
        
        detectedMotifs.put(MotifType.REPETITION, repetitionMotifs);
        detectedMotifs.put(MotifType.VARIATION, variationMotifs);
        detectedMotifs.put(MotifType.RHYTHMIC, rhythmicMotifs);
        
        return detectedMotifs;
    }
    
    private HashMap<Double [], Integer> getPotentialBaseMotifs(IPhrase iPhrase)
    {
        IHanson iHanson = iPhrase.getPostHansonValues();
        HashMap<Double [], Integer> intervalPatterns = new HashMap();
        ArrayList<Double> intervals = iHanson.getIntervals();
        
        for(int size = MAX_MOTIF_LENGTH; size >= MIN_MOTIF_LENGTH; size--)
        {
            for(int i = 0; i < intervals.size()-size; i++)
            {
                Double []intervalPattern = new Double[size];
                
                for(int j = 0; j < size; j++)
                    intervalPattern[j] = intervals.get(i+j);
                
                boolean exist = false;
                for(Double[] existingPattern:intervalPatterns.keySet())
                {
                    if(existingPattern.length == intervalPattern.length)
                    {
                        boolean match = true;
                        for(int index = 0; index < existingPattern.length; index++)
                        {
                            if(existingPattern[index].doubleValue() != intervalPattern[index].doubleValue())
                                match = false;
                        }
                        
                        if(match)
                        {
                            exist = true;
                            break;
                        }
                    }
                }
                
                if(!exist)
                    intervalPatterns.put(intervalPattern, i);
            }
        }
        
        return intervalPatterns;
    }
}
