package jp.crestmuse.cmx.bayesband.inference;

import jp.crestmuse.cmx.inference.*;
import jp.crestmuse.cmx.inference.MusicRepresentation.MusicElement;

public class NaiveVoicingCalculator implements Calculator {

  // private MusicRepresentation musicRepresentation;
  private static final int BASE_NN = 36;
  private static final int[][] basslines = new int[][] { { 0, 4, 7, 0 },
      { 2, 0, -3, 2 }, { 4, -1, -5, 4 }, { -7, 0, 5, -7 }, { -5, 7, 2, -5 },
      { -3, -1, 0, -3 }, { -1, 0, 1, 2 } };

  public void update(MusicRepresentation musRep, MusicElement me, int index) {
    /*
    MusicElement vh = musicRepresentation.getVoicingHighElement(index);
    MusicElement vmh = musicRepresentation.getVoicingMidHighElement(index);
    MusicElement vml = musicRepresentation.getVoicingMidLowElement(index);
    MusicElement vl = musicRepresentation.getVoicingLowElement(index);
    */
    MusicElement vh = musRep.getMusicElement("voicingHigh", index);
    MusicElement vmh = musRep.getMusicElement("voicingMidHigh", index);
    MusicElement vml = musRep.getMusicElement("voicingMidLow", index);
    MusicElement vl = musRep.getMusicElement("voicingLow", index);
    int highestIndex = me.getHighestProbIndex();
    // 連発防止
    // 前の小節と前の前の小節とコードが同じなら二位のコードを採用
    if (index > musRep.getDivision()
        && musRep.getMusicElement("chord", index - musRep.getDivision())
            .getHighestProbIndex() == highestIndex
        && musRep.getMusicElement("chord", index - musRep.getDivision() * 2)
            .getHighestProbIndex() == highestIndex) {
      int tmp = me.getRankedProbIndex(1);
      if (me.getProb(tmp) > 0.0)
        highestIndex = tmp;
      // musicRepresentation.getChordElement(index).setEvidence(highestIndex);
      musRep.getMusicElement("chord", index).setEvidence(highestIndex);
    }
    int[] map = diatonicMapC(me.getLabel(highestIndex));
    vh.setProb(map[0], me.getProb(highestIndex));
    vmh.setProb(map[1], me.getProb(highestIndex));
    vml.setProb(map[2], me.getProb(highestIndex));
    vl.setProb(map[3], me.getProb(highestIndex));
    // MusicElement bass = musicRepresentation.getBassElement(index);
    MusicElement bass = musRep.getMusicElement("bass", index);
    for (int i = 0; i < 4; i++) {
      // bass = musicRepresentation.getBassElement(index + (i) * 2);
      bass = musRep.getMusicElement("bass", index + i * 2);
      bass.setEvidence(BASE_NN + basslines[highestIndex][i]);
    }
  }

  private int[] diatonicMapC(String chord) {
    int[] diatonic;
    if (chord.equals("C"))
      diatonic = new int[] { 55, 57, 60, 64 };
    else if (chord.equals("Dm"))
      diatonic = new int[] { 57, 60, 62, 65 };
    else if (chord.equals("Em"))
      diatonic = new int[] { 59, 62, 64, 67 };
    else if (chord.equals("F"))
      diatonic = new int[] { 57, 60, 62, 65 };
    else if (chord.equals("G"))
      diatonic = new int[] { 55, 59, 62, 65 };
    else if (chord.equals("Am"))
      diatonic = new int[] { 55, 57, 60, 64 };
    else
      diatonic = new int[] { 57, 59, 62, 65 }; // B(b5)
    return diatonic;
  }

}
