/*
 *  Copyright (C) 2016 Dimitry Polivaev
 *  
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 */
package org.dpolivaev.mnemonicsetter;

import static org.junit.Assert.assertThat;

import java.awt.event.KeyEvent;
import java.util.Collections;

import org.hamcrest.CoreMatchers;
import org.junit.Test;

public class ItemMnemonicSetterShould {
	static class MnemonicHolder implements INameMnemonicHolder{

		private String text;
		private int keyCode;

		public MnemonicHolder(String text, char character) {
			super();
			setText(text);
			setMnemonic(character);
		}

		public MnemonicHolder(String text) {
			setText(text);
		}

		@Override
		public String getText() {
			return text;
		}

		@Override
		public void setDisplayedMnemonicIndex(int mnemoSignIndex) {
		}

		@Override
		public void setMnemonic(char character) {
			final int keyCode = KeyEvent.getExtendedKeyCodeForChar(character);
			setMnemonic(keyCode);
		}

		@Override
		public void setMnemonic(final int keyCode) {
			this.keyCode = keyCode;
		}

		@Override
		public void setText(String text) {
			this.text = text;
		}

		@Override
		public int getMnemonic() {
			return keyCode;
		}

		@Override
		public boolean hasAccelerator() {
			return false;
		}

	}

	private void assertMnemonic(final MnemonicHolder mnemonicHolder, char character) {
		final int keyCode = character != 0 ? KeyEvent.getExtendedKeyCodeForChar(character) : 0;
		final int mnemonic = mnemonicHolder.getMnemonic();
		if(keyCode == 0)
			assertThat(mnemonic, CoreMatchers.equalTo(keyCode));
		else {
			final String mnemonicCharacter = KeyEvent.getKeyText(mnemonic);
			final String expectedCharacter = KeyEvent.getKeyText(keyCode);
			assertThat(mnemonicCharacter, CoreMatchers.equalTo(expectedCharacter));
		}
	}


	@Test
	public void assignsFirstLetter() throws Exception {
		final MnemonicHolder mnemonicHolderA = new MnemonicHolder("A");
		ItemMnemonicSetter.of(mnemonicHolderA).setMnemonics();
		assertMnemonic(mnemonicHolderA, 'A');
	}


	@Test
	public void skipsSpaces() throws Exception {
		final MnemonicHolder mnemonicHolderA = new MnemonicHolder(" A");
		ItemMnemonicSetter.of(mnemonicHolderA).setMnemonics();
		assertMnemonic(mnemonicHolderA, 'A');
	}
	
	@Test
	public void assignsSecondLetter_IfFirstLetterIsAlreadyAssigned() throws Exception {
		final MnemonicHolder mnemonicHolderAB = new MnemonicHolder("AB");
		final MnemonicHolder mnemonicHolderA = new MnemonicHolder("A", 'A');
		ItemMnemonicSetter.of(mnemonicHolderAB, mnemonicHolderA).setMnemonics();
		assertMnemonic(mnemonicHolderA, 'A');
		assertMnemonic(mnemonicHolderAB, 'B');
	}

	@Test
	public void assignsSecondLetter_IfFirstLetterIsAlreadyUsed() throws Exception {
		final MnemonicHolder mnemonicHolderAB = new MnemonicHolder("AB");
		ItemMnemonicSetter.of(mnemonicHolderAB).notUsing(Collections.singleton(KeyEvent.VK_A)).setMnemonics();
		assertMnemonic(mnemonicHolderAB, 'B');
	}

	@Test
	public void assignsSecondLetter_IfFirstLetterLowerCaseIsAlreadyAssigned() throws Exception {
		final MnemonicHolder mnemonicHolderAB = new MnemonicHolder("ab");
		final MnemonicHolder mnemonicHolderA = new MnemonicHolder("A", 'A');
		ItemMnemonicSetter.of(mnemonicHolderAB, mnemonicHolderA).setMnemonics();
		assertMnemonic(mnemonicHolderA, 'A');
		assertMnemonic(mnemonicHolderAB, 'B');
	}
	
	@Test
	public void assignsFirstLetter_ifItIsNotAssignedYet() throws Exception {
		final MnemonicHolder mnemonicHolderAB = new MnemonicHolder("AB");
		final MnemonicHolder mnemonicHolderA = new MnemonicHolder("C");
		ItemMnemonicSetter.of(mnemonicHolderAB, mnemonicHolderA).setMnemonics();
		assertMnemonic(mnemonicHolderAB, 'A');
	}
	
	@Test
	public void assignsFirstLetter_toSecondHolder() throws Exception {
		final MnemonicHolder mnemonicHolderAB = new MnemonicHolder("AB");
		final MnemonicHolder mnemonicHolderC = new MnemonicHolder("C");
		ItemMnemonicSetter.of(mnemonicHolderAB, mnemonicHolderC).setMnemonics();
		assertMnemonic(mnemonicHolderAB, 'A');
		assertMnemonic(mnemonicHolderC, 'C');
	}
	
	@Test
	public void assignsSecondLetter_toSecondHolder() throws Exception {
		final MnemonicHolder mnemonicHolderAB = new MnemonicHolder("AB");
		final MnemonicHolder mnemonicHolderAC = new MnemonicHolder("AC");
		ItemMnemonicSetter.of(mnemonicHolderAB, mnemonicHolderAC).setMnemonics();
		assertMnemonic(mnemonicHolderAB, 'A');
		assertMnemonic(mnemonicHolderAC, 'C');
	}
	
	@Test
	public void assignsNoLetter_ifAllLettersAreAlreadyAssigned() throws Exception {
		final MnemonicHolder mnemonicHolderA1 = new MnemonicHolder("a");
		final MnemonicHolder mnemonicHolderA2 = new MnemonicHolder("a", 'A');
		ItemMnemonicSetter.of(mnemonicHolderA1, mnemonicHolderA2).setMnemonics();
		assertMnemonic(mnemonicHolderA1, '\0');
		assertMnemonic(mnemonicHolderA2, 'A');
	}
	
	@Test
	public void assignsSecondLetter_toFirstHolder() throws Exception {
		final MnemonicHolder mnemonicHolderAB = new MnemonicHolder("AB");
		final MnemonicHolder mnemonicHolderA = new MnemonicHolder("A");
		ItemMnemonicSetter.of(mnemonicHolderAB, mnemonicHolderA).setMnemonics();
		assertMnemonic(mnemonicHolderAB, 'B');
		assertMnemonic(mnemonicHolderA, 'A');
	}

	@Test
	public void assignsNoLetter_toSecondHolder() throws Exception {
		final MnemonicHolder mnemonicHolderA1 = new MnemonicHolder("a");
		final MnemonicHolder mnemonicHolderA2 = new MnemonicHolder("a");
		ItemMnemonicSetter.of(mnemonicHolderA1, mnemonicHolderA2).setMnemonics();
		assertMnemonic(mnemonicHolderA1, 'A');
		assertMnemonic(mnemonicHolderA2, '\0');
	}
}
