package jp.crestmuse.cmx.amusaj.commands;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;

import org.xml.sax.SAXException;

import jp.crestmuse.cmx.amusaj.filewrappers.ArffWrapper;
import jp.crestmuse.cmx.commands.CMXCommand;
import jp.crestmuse.cmx.filewrappers.FileWrapperCompatible;
import jp.crestmuse.cmx.filewrappers.InvalidFileTypeException;
import jp.crestmuse.cmx.filewrappers.SCCXMLWrapper;
import jp.crestmuse.cmx.filewrappers.SCCXMLWrapper.Annotation;
import jp.crestmuse.cmx.filewrappers.SCCXMLWrapper.Note;

/**
 * 複数のSCCからARFFを生成して返す． デフォルトで標準出力に書き出す． ファイルに書き出したい場合はpostprocをいじる．
 */
public class SCC2ARFF080811model3 extends
    CMXCommand<FileWrapperCompatible, FileWrapperCompatible> {

  /**
   * 最終的に書き出すARFF
   */
  private ArffWrapper arff;

  SCC2ARFF080811model3() {
    arff = new ArffWrapper("chord");

    // 学習データ内に存在する可能性のあるNoteナンバー．
    // 12種類に圧縮している
    String[] notenums = ARFFFunctions.notenums_div12;

    // 存在する可能性のあるコード M,m,aug,dim,(#5),(b5)
    String[] chords = ARFFFunctions.diatonic_chords;
    
     
    arff.addAttribute("PrevNote", notenums);
    arff.addAttribute("PrevChord", chords);
    arff.addAttribute("CurrentNote", notenums);
    arff.addAttribute("CurrentChord", chords);
    arff.addAttribute("NextNote", notenums);
    arff.addAttribute("NextChord", chords);
  }

  protected FileWrapperCompatible run(FileWrapperCompatible f)
      throws IOException, ParserConfigurationException, SAXException,
      TransformerException, InvalidFileTypeException {
    SCCXMLWrapper scc = (SCCXMLWrapper) f;
    ChordConverter cc = new ChordConverter();
    
    //未入力フラグ
    int pprevNote = -1;
    String pprevChord = null;
    int prevNote = -1;
    String prevChord = null;
    
    // 曲のキーを取得
    String musickey = ARFFFunctions.getMusicKey(scc);
    if(musickey == null) return null;
    
    
    for (Annotation a : scc.getChordList()) {
      String currentChord = a.content(); //コード取得
      // 謎のデータをスキップ
      if (currentChord.equals("D'"))
        continue;

      
      int currentNote = -1;
      for(Note n : scc.getPartList()[0].getNoteList()){
	        if (n.onset() >= a.onset()) {
	          currentNote = n.notenum() % 12;
	          break;
	        }
	  }
      if (currentNote == -1) return null;
      
      currentNote = cc.noteTransfer(musickey, currentNote);
      
      //currentChordが"/"の時はprevChordを代入
      currentChord = cc.chordOmitter(cc.chordTransfer(musickey, currentChord));
      if(currentChord.equals("/")){
    	  currentChord = prevChord;
      }
      
      
      if (pprevChord!= null && pprevNote != -1) {
    	  //ChordConverterの無視するコードに該当するものが無いなら書き込むつもりの処理
    	  if(pprevChord.matches(ARFFFunctions.diatonic_chords_RegExp)
    			  && prevChord.matches(ARFFFunctions.diatonic_chords_RegExp)
    			  && currentChord.matches(ARFFFunctions.diatonic_chords_RegExp)){
	        arff.addData(pprevNote + "," + pprevChord + "," + prevNote + "," + prevChord + "," + currentNote + ","
	            + currentChord);
    	  }
      }
      
      
      prevNote = -1;
      for(Note n : scc.getPartList()[0].getNoteList()){
    	  if(n.onset() < a.offset()){
    		  pprevNote = prevNote;
    		  prevNote = n.notenum();
    	  }
    	  else{
    		  break;
    	  }
      }
      if(prevNote == -1 || pprevNote == -1){
    	  continue;
      }
      else{
    	  prevNote %= 12;
    	  prevNote = cc.noteTransfer(musickey, prevNote);
    	  pprevNote %= 12;
    	  pprevNote = cc.noteTransfer(musickey, pprevNote);
      }
      
      pprevChord = prevChord;
      prevChord = currentChord;
    }
    return null;
  }

  protected void postproc() throws IOException, ParserConfigurationException,
      SAXException, TransformerException {
    FileOutputStream out = new FileOutputStream(new File("080811model3.arff"));
    arff.write(out);
  }

  public static void main(String[] args) {
	  
    SCC2ARFF080811model3 s2a = new SCC2ARFF080811model3();
    
    try {
      s2a.start(args);
    } catch (Exception e) {
      e.printStackTrace();
    }
    
	  //System.out.println("ugoita--!");
  }

}
