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

import hanson.HansonParser;

/**
 *
 * @author smuRf
 */
public class VariationMotifDetectorHanson implements MotifDetector{
    private static int ALLOWED_INTERVAL_VARIATION;
    private String type = "";
    
    public void setAllowedIntervalVariation(int aiv)
    {
        ALLOWED_INTERVAL_VARIATION = aiv;
    }
    
    @Override
    public boolean detect(int intervalStartIndex, Double[] postIntervals, Double[] preIntervals, Double[] postIntervalPattern, Double[] preIntervalPattern, Double[] durations, Double[] durationsPattern) {
        // krebs
        double[] newIntervalPattern = new double[postIntervalPattern.length];
        int index = 0;
        for(double value:postIntervalPattern)
        {
            String hansonStr = HansonParser.getStringForValue(value);
            if(hansonStr.charAt(2) == 'r')
                hansonStr = hansonStr.replaceFirst("r", "l");
            else if(hansonStr.charAt(2) == 'l')
                hansonStr = hansonStr.replaceFirst("l", "r");

            newIntervalPattern[(newIntervalPattern.length-1)-index] = HansonParser.getDoubleForString(hansonStr);
            index++;
        }
        
        boolean equal = true;
        type = "reverse";
        for(int k = 0; k < newIntervalPattern.length; k++)
        {
            if(preIntervals[k].doubleValue() != newIntervalPattern[k] ||
               durations[k].doubleValue() != durationsPattern[(newIntervalPattern.length-1)-k].doubleValue())
            {
                equal = false;
                type = "";
                break;
            }
        }
        
        // inversion
        if(!equal)
        {
            equal = true;
            type = "inversion";
            for(int k = 0; k < postIntervalPattern.length; k++)
            {
                String hansonStr = HansonParser.getStringForValue(postIntervalPattern[k].doubleValue());

                if(hansonStr.charAt(2) == 'r')
                    hansonStr = hansonStr.replaceFirst("r", "l");
                else if(hansonStr.charAt(2) == 'l')
                    hansonStr = hansonStr.replaceFirst("l", "r");

                double value = HansonParser.getDoubleForString(hansonStr);

                if(postIntervals[k].doubleValue() != value ||
                   durations[k].doubleValue() != durationsPattern[k].doubleValue())
                {
                    equal = false;
                    type = "";
                    break;
                }
            }
        }
        
        //interval changes
        if(!equal)
        {
            equal = true;
            int intervalChangeCount = 0;
            type = "interval change";
            double intervalsK;
            double intervalPatternK;
            for(int k = 0; k < postIntervalPattern.length-1; k++)
            {
                intervalsK = postIntervals[k];
                intervalPatternK = postIntervalPattern[k];
                
                if(durations[k].doubleValue() != durationsPattern[k].doubleValue())
                {
                    equal = false;
                    break;
                }
                else
                {
                    String hansonPatternStr = HansonParser.getStringForValue(intervalPatternK);
                    String hansonIntervalStr = HansonParser.getStringForValue(intervalsK);
                    
                    if(hansonPatternStr.charAt(2) == hansonIntervalStr.charAt(2))
                    {
                        int notePatternInterval = (int) (intervalPatternK/1000);
                        int notePatternOctave = ((int) ((intervalPatternK-(notePatternInterval*1000))/100));
                        int noteInterval = (int) (intervalsK/1000);
                        int noteOctave = (int) ((intervalsK-(noteInterval*1000))/100);
                        
                        notePatternInterval = notePatternInterval + notePatternOctave*6;
                        noteInterval = noteInterval + noteOctave*6;
                        
                        if(Math.abs(noteInterval-notePatternInterval) > ALLOWED_INTERVAL_VARIATION)
                        {
                            equal = false;
                            break;
                        }
                        else if(Math.abs(noteInterval-notePatternInterval) > 0 &&
                                Math.abs(noteInterval-notePatternInterval) <= ALLOWED_INTERVAL_VARIATION)
                            intervalChangeCount++;
                    }
                    else
                    {
                        equal = false;
                        break;
                    }
                }
            }
            if(!equal || intervalChangeCount == 0)
            {
                type = "";
                equal = false;
            }
        }
        
        return equal;
    }

    @Override
    public String getType() {
        return type;
    }
}
