import { MusicSheetReader }       from "../../../src/MusicalScore/ScoreIO/MusicSheetReader";
import { MusicSheet }             from "../../../src/MusicalScore/MusicSheet";
import { IXmlElement }            from "../../../src/Common/FileIO/Xml";
import { KeyInstruction }         from "../../../src/MusicalScore/VoiceData/Instructions/KeyInstruction";
import { KeyEnum as KeyModeEnum } from "../../../src/MusicalScore/VoiceData/Instructions/KeyInstruction";
import * as chai                  from "chai";
let reader: MusicSheetReader;
let parser: DOMParser;
/* tslint:disable:no-unused-expression */
describe("MusicXML parser for element 'key'", () => {
  before((): void => {
    reader = new MusicSheetReader();
    parser = new DOMParser();
  });
  describe("for group traditional keys", () => {
    xit("enforces single occurrence of element 'fifths'", (done: MochaDone) => {
      const keyInstruction: KeyInstruction = getIllegalMusicXmlWithTwoFifthsElements().getFirstSourceMeasure().getKeyInstruction(0);
      // TODO Make sure we detect the multiple fifths and react properly
      chai.expect(keyInstruction.Mode).to.equal(KeyModeEnum.none);
      done();
    });
    it("reads key signature with no optional 'mode' element present", (done: MochaDone) => {
      const keyInstruction: KeyInstruction = getMusicSheetWithKey(0, undefined).getFirstSourceMeasure().getKeyInstruction(0);
      chai.expect(keyInstruction.Key).to.equal(0);
      chai.expect(keyInstruction.Mode).to.equal(KeyModeEnum.none);
      done();
    });
    describe("major keys", () => {
      it("reads key signature C-major", (done: MochaDone) => {
        const keyInstruction: KeyInstruction = getMusicSheetWithKey(0, "major").getFirstSourceMeasure().getKeyInstruction(0);
        chai.expect(keyInstruction.Key).to.equal(0);
        chai.expect(keyInstruction.Mode).to.equal(KeyModeEnum.major);
        done();
      });
      it("reads key signature G-major", (done: MochaDone) => {
        const keyInstruction: KeyInstruction = getMusicSheetWithKey(1, "major").getFirstSourceMeasure().getKeyInstruction(0);
        chai.expect(keyInstruction.Key).to.equal(1);
        chai.expect(keyInstruction.Mode).to.equal(KeyModeEnum.major);
        done();
      });
      it("reads key signature D-major", (done: MochaDone) => {
        const keyInstruction: KeyInstruction = getMusicSheetWithKey(2, "major").getFirstSourceMeasure().getKeyInstruction(0);
        chai.expect(keyInstruction.Key).to.equal(2);
        chai.expect(keyInstruction.Mode).to.equal(KeyModeEnum.major);
        done();
      });
      it("reads key signature A-major", (done: MochaDone) => {
        const keyInstruction: KeyInstruction = getMusicSheetWithKey(3, "major").getFirstSourceMeasure().getKeyInstruction(0);
        chai.expect(keyInstruction.Key).to.equal(3);
        chai.expect(keyInstruction.Mode).to.equal(KeyModeEnum.major);
        done();
      });
      it("reads key signature E-major", (done: MochaDone) => {
        const keyInstruction: KeyInstruction = getMusicSheetWithKey(4, "major").getFirstSourceMeasure().getKeyInstruction(0);
        chai.expect(keyInstruction.Key).to.equal(4);
        chai.expect(keyInstruction.Mode).to.equal(KeyModeEnum.major);
        done();
      });
      it("reads key signature B-major", (done: MochaDone) => {
        const keyInstruction: KeyInstruction = getMusicSheetWithKey(5, "major").getFirstSourceMeasure().getKeyInstruction(0);
        chai.expect(keyInstruction.Key).to.equal(5);
        chai.expect(keyInstruction.Mode).to.equal(KeyModeEnum.major);
        done();
      });
      it("reads key signature Fis-major", (done: MochaDone) => {
        const keyInstruction: KeyInstruction = getMusicSheetWithKey(6, "major").getFirstSourceMeasure().getKeyInstruction(0);
        chai.expect(keyInstruction.Key).to.equal(6);
        chai.expect(keyInstruction.Mode).to.equal(KeyModeEnum.major);
        done();
      });
      it("reads key signature Cis-major", (done: MochaDone) => {
        const keyInstruction: KeyInstruction = getMusicSheetWithKey(7, "major").getFirstSourceMeasure().getKeyInstruction(0);
        chai.expect(keyInstruction.Key).to.equal(7);
        chai.expect(keyInstruction.Mode).to.equal(KeyModeEnum.major);
        done();
      });
      it("reads key signature Gis-major", (done: MochaDone) => {
        const keyInstruction: KeyInstruction = getMusicSheetWithKey(8, "major").getFirstSourceMeasure().getKeyInstruction(0);
        chai.expect(keyInstruction.Key).to.equal(8);
        chai.expect(keyInstruction.Mode).to.equal(KeyModeEnum.major);
        done();
      });
      it("reads key signature F-major", (done: MochaDone) => {
        const keyInstruction: KeyInstruction = getMusicSheetWithKey(-1, "major").getFirstSourceMeasure().getKeyInstruction(0);
        chai.expect(keyInstruction.Key).to.equal(-1);
        chai.expect(keyInstruction.Mode).to.equal(KeyModeEnum.major);
        done();
      });
      it("reads key signature B-major", (done: MochaDone) => {
        const keyInstruction: KeyInstruction = getMusicSheetWithKey(-2, "major").getFirstSourceMeasure().getKeyInstruction(0);
        chai.expect(keyInstruction.Key).to.equal(-2);
        chai.expect(keyInstruction.Mode).to.equal(KeyModeEnum.major);
        done();
      });
      it("reads key signature Es-major", (done: MochaDone) => {
        const keyInstruction: KeyInstruction = getMusicSheetWithKey(-3, "major").getFirstSourceMeasure().getKeyInstruction(0);
        chai.expect(keyInstruction.Key).to.equal(-3);
        chai.expect(keyInstruction.Mode).to.equal(KeyModeEnum.major);
        done();
      });
      it("reads key signature As-major", (done: MochaDone) => {
        const keyInstruction: KeyInstruction = getMusicSheetWithKey(-4, "major").getFirstSourceMeasure().getKeyInstruction(0);
        chai.expect(keyInstruction.Key).to.equal(-4);
        chai.expect(keyInstruction.Mode).to.equal(KeyModeEnum.major);
        done();
      });
      it("reads key signature Des-major", (done: MochaDone) => {
        const keyInstruction: KeyInstruction = getMusicSheetWithKey(-5, "major").getFirstSourceMeasure().getKeyInstruction(0);
        chai.expect(keyInstruction.Key).to.equal(-5);
        chai.expect(keyInstruction.Mode).to.equal(KeyModeEnum.major);
        done();
      });
      it("reads key signature Ges-major", (done: MochaDone) => {
        const keyInstruction: KeyInstruction = getMusicSheetWithKey(-6, "major").getFirstSourceMeasure().getKeyInstruction(0);
        chai.expect(keyInstruction.Key).to.equal(-6);
        chai.expect(keyInstruction.Mode).to.equal(KeyModeEnum.major);
        done();
      });
      it("reads key signature Fes-major", (done: MochaDone) => {
        const keyInstruction: KeyInstruction = getMusicSheetWithKey(-8, "major").getFirstSourceMeasure().getKeyInstruction(0);
        chai.expect(keyInstruction.Key).to.equal(-8);
        chai.expect(keyInstruction.Mode).to.equal(KeyModeEnum.major);
        done();
      });
    });
    describe("minor keys", () => {
      it("reads key signature a-minor", (done: MochaDone) => {
        const keyInstruction: KeyInstruction = getMusicSheetWithKey(0, "minor").getFirstSourceMeasure().getKeyInstruction(0);
        chai.expect(keyInstruction.Key).to.equal(0);
        chai.expect(keyInstruction.Mode).to.equal(KeyModeEnum.minor);
        done();
      });
      it("reads key signature e-minor", (done: MochaDone) => {
        const keyInstruction: KeyInstruction = getMusicSheetWithKey(1, "minor").getFirstSourceMeasure().getKeyInstruction(0);
        chai.expect(keyInstruction.Key).to.equal(1);
        chai.expect(keyInstruction.Mode).to.equal(KeyModeEnum.minor);
        done();
      });
      it("reads key signature b-minor", (done: MochaDone) => {
        const keyInstruction: KeyInstruction = getMusicSheetWithKey(2, "minor").getFirstSourceMeasure().getKeyInstruction(0);
        chai.expect(keyInstruction.Key).to.equal(2);
        chai.expect(keyInstruction.Mode).to.equal(KeyModeEnum.minor);
        done();
      });
      it("reads key signature fis-minor", (done: MochaDone) => {
        const keyInstruction: KeyInstruction = getMusicSheetWithKey(3, "minor").getFirstSourceMeasure().getKeyInstruction(0);
        chai.expect(keyInstruction.Key).to.equal(3);
        chai.expect(keyInstruction.Mode).to.equal(KeyModeEnum.minor);
        done();
      });
      it("reads key signature cis-minor", (done: MochaDone) => {
        const keyInstruction: KeyInstruction = getMusicSheetWithKey(4, "minor").getFirstSourceMeasure().getKeyInstruction(0);
        chai.expect(keyInstruction.Key).to.equal(4);
        chai.expect(keyInstruction.Mode).to.equal(KeyModeEnum.minor);
        done();
      });
      it("reads key signature gis-minor", (done: MochaDone) => {
        const keyInstruction: KeyInstruction = getMusicSheetWithKey(5, "minor").getFirstSourceMeasure().getKeyInstruction(0);
        chai.expect(keyInstruction.Key).to.equal(5);
        chai.expect(keyInstruction.Mode).to.equal(KeyModeEnum.minor);
        done();
      });
      it("reads key signature dis-minor", (done: MochaDone) => {
        const keyInstruction: KeyInstruction = getMusicSheetWithKey(6, "minor").getFirstSourceMeasure().getKeyInstruction(0);
        chai.expect(keyInstruction.Key).to.equal(6);
        chai.expect(keyInstruction.Mode).to.equal(KeyModeEnum.minor);
        done();
      });
      it("reads key signature ais-minor", (done: MochaDone) => {
        const keyInstruction: KeyInstruction = getMusicSheetWithKey(7, "minor").getFirstSourceMeasure().getKeyInstruction(0);
        chai.expect(keyInstruction.Key).to.equal(7);
        chai.expect(keyInstruction.Mode).to.equal(KeyModeEnum.minor);
        done();
      });
      it("reads key signature d-minor", (done: MochaDone) => {
        const keyInstruction: KeyInstruction = getMusicSheetWithKey(-1, "minor").getFirstSourceMeasure().getKeyInstruction(0);
        chai.expect(keyInstruction.Key).to.equal(-1);
        chai.expect(keyInstruction.Mode).to.equal(KeyModeEnum.minor);
        done();
      });
      it("reads key signature g-minor", (done: MochaDone) => {
        const keyInstruction: KeyInstruction = getMusicSheetWithKey(-2, "minor").getFirstSourceMeasure().getKeyInstruction(0);
        chai.expect(keyInstruction.Key).to.equal(-2);
        chai.expect(keyInstruction.Mode).to.equal(KeyModeEnum.minor);
        done();
      });
      it("reads key signature c-minor", (done: MochaDone) => {
        const keyInstruction: KeyInstruction = getMusicSheetWithKey(-3, "minor").getFirstSourceMeasure().getKeyInstruction(0);
        chai.expect(keyInstruction.Key).to.equal(-3);
        chai.expect(keyInstruction.Mode).to.equal(KeyModeEnum.minor);
        done();
      });
      it("reads key signature f-minor", (done: MochaDone) => {
        const keyInstruction: KeyInstruction = getMusicSheetWithKey(-4, "minor").getFirstSourceMeasure().getKeyInstruction(0);
        chai.expect(keyInstruction.Key).to.equal(-4);
        chai.expect(keyInstruction.Mode).to.equal(KeyModeEnum.minor);
        done();
      });
      it("reads key signature bb-minor", (done: MochaDone) => {
        const keyInstruction: KeyInstruction = getMusicSheetWithKey(-5, "minor").getFirstSourceMeasure().getKeyInstruction(0);
        chai.expect(keyInstruction.Key).to.equal(-5);
        chai.expect(keyInstruction.Mode).to.equal(KeyModeEnum.minor);
        done();
      });
      it("reads key signature es-minor", (done: MochaDone) => {
        const keyInstruction: KeyInstruction = getMusicSheetWithKey(-6, "minor").getFirstSourceMeasure().getKeyInstruction(0);
        chai.expect(keyInstruction.Key).to.equal(-6);
        chai.expect(keyInstruction.Mode).to.equal(KeyModeEnum.minor);
        done();
      });
      it("reads key signature as-minor", (done: MochaDone) => {
        const keyInstruction: KeyInstruction = getMusicSheetWithKey(-7, "minor").getFirstSourceMeasure().getKeyInstruction(0);
        chai.expect(keyInstruction.Key).to.equal(-7);
        chai.expect(keyInstruction.Mode).to.equal(KeyModeEnum.minor);
        done();
      });
    });
  });
});
function getMusicSheetWithKey(fifths: number = undefined, mode: string = undefined): MusicSheet {
  const doc: Document = parser.parseFromString(getMusicXmlWithKey(fifths, mode), "text/xml");
  chai.expect(doc).to.not.be.undefined;
  const score: IXmlElement = new IXmlElement(doc.getElementsByTagName("score-partwise")[0]);
  chai.expect(score).to.not.be.undefined;
  return reader.createMusicSheet(score, "template.xml");
}
function getMusicXmlWithKey(fifths: number = undefined, mode: string = undefined): string {
  const modeElement: string = mode ? `${mode}` : "";
  const fifthsElement: string = fifths ? `${fifths}` : "";
  return `
          
          
            
              
                Music
              
            
            
              
                
                  1
                  
                    ${fifthsElement}
                    ${modeElement}
                  
                  
                  
                    G
                    2
                  
                
                
                  
                    C
                    4
                  
                  4
                  whole
                
              
            
          `;
}
function getIllegalMusicXmlWithTwoFifthsElements(): MusicSheet {
  const doc: Document = parser.parseFromString(
    `
      
      
        
          
            Music
          
        
        
          
            
              1
              
                1
                2
                3
              
              
              
                G
                2
              
            
            
              
                C
                4
              
              4
              whole
            
          
        
      `,
    "text/xml"
  );
  chai.expect(doc).to.not.be.undefined;
  const score: IXmlElement = new IXmlElement(doc.getElementsByTagName("score-partwise")[0]);
  chai.expect(score).to.not.be.undefined;
  return reader.createMusicSheet(score, "template.xml");
}