package charactermanaj.model.io;

import java.util.List;

import charactermanaj.model.CharacterData;
import charactermanaj.model.RecommendationURL;
import charactermanaj.model.io.CharacterDataDefaultProvider.DefaultCharacterDataVersion;

/**
 * デフォルトキャラクターセット用のお薦めURLを補完・補完解除します。<br>
 * <br>
 * ※ これは黒魔術的に置き換えるためのものなので、XMLの書き込み時には
 * デフォルトキャラクターセットv2, v3に該当するもので、同一のお勧めリストであれば
 * それをnullに変える。<br>
 * ただし、デフォルトキャラクターセットv2, v3の定義もXMLであるため、
 * XML読み込み中のタイミングでnullを既定のお勧めリストとして補完しようとすると
 * 循環してしまうため、XML読み込み後に補間する必要があることに注意。<br>
 */
public final class RecommendationURLCompensator {

	/**
	 * シングルトン
	 */
	private static final RecommendationURLCompensator INST = new RecommendationURLCompensator();

	/**
	 * プライ弁ーとコンストラクタ
	 */
	private RecommendationURLCompensator() {
		super();
	}

	/**
	 * シングルトンインスタンすを取得する
	 * @return
	 */
	public static RecommendationURLCompensator getInstance() {
		return INST;
	}

	/**
	 * お勧めリンクリストが設定されていない場合(nullの場合)、デフォルトのお勧めリストを設定する.<br>
	 * すでに設定されている場合(空を含む)は何もしない.<br>
	 * <br>
	 * おすすめリンクがサポートされてなかったころのデータは、おすすめリンク用のタグそのものが存在せずnullとなる.<br>
	 * サポート後のデータでリンクを未設定にしている場合は、空のリストとなる.<br>
	 * したがって、nullの場合のみ、おすすめリンクを補完する.<br>
	 *
	 * @param characterData
	 *            キャラクターデータ
	 */
	public void compensateRecommendationList(CharacterData characterData) {
		if (characterData == null) {
			throw new IllegalArgumentException();
		}

		// キャラクターデータの構造がデフォルトのv2, v3と同一であれば、対応するリンクを設定する
		List<RecommendationURL> recommendations = getCompensateRecommendationList(characterData);
		if (recommendations != null) {
			characterData.setRecommendationURLList(recommendations);
		}
	}

	/**
	 * キャラクターデータに対するお勧めリストの補完が必要であれば、そのリストを返す。
	 * すでに設定済みであるか、対応する補完リストがない場合はnullを返す。
	 * @param characterData
	 * @return お勧めリスト、もしくはnull
	 */
	public List<RecommendationURL> getCompensateRecommendationList(CharacterData characterData) {
		if (characterData != null && characterData.getRecommendationURLList() == null) {
			// 補填の必要ある場合のみ
			CharacterDataDefaultProvider defProv = new CharacterDataDefaultProvider();
			for (DefaultCharacterDataVersion dataVersion : DefaultCharacterDataVersion.values()) {
				CharacterData defaultCd = defProv.createDefaultCharacterData(dataVersion);
				if (defaultCd.toSignatureString().equals(characterData.toSignatureString())) {
					return defaultCd.getRecommendationURLList();
				}
			}
		}
		return null;
	}

	/**
	 * 補完されたものを除いたお勧めリストを取得する。
	 * デフォルト構造でデフォルトと同一のお勧めリストの場合、補完されたものとしてnullを返す。
	 * それ以外はお勧めリストをそのまま返す。
	 * @param cd
	 */
	public List<RecommendationURL> getUncompensateRecommendationList(CharacterData cd) {
		if (cd == null) {
			return null;
		}

		// デフォルトのキャラクターデータ構造で、
		// お勧めリストと内容が同じの場合は、明示的にリストを設定しない.
		String cdSig = cd.toStructureString();
		List<RecommendationURL> recommendations = cd.getRecommendationURLList();
		if (recommendations != null) {
			CharacterDataDefaultProvider defProv = new CharacterDataDefaultProvider();
			for (DefaultCharacterDataVersion dataVersion : DefaultCharacterDataVersion.values()) {
				CharacterData defaultCd = defProv.createDefaultCharacterData(dataVersion);
				String defSig = defaultCd.toStructureString();
				if (cdSig.equals(defSig)) {
					List<RecommendationURL> defaultRecommendationURLList = defaultCd.getRecommendationURLList();
					if (defaultRecommendationURLList != null && defaultRecommendationURLList.equals(recommendations)) {
						recommendations = null;
						break;
					}
				}
			}
		}
		return recommendations;
	}
}
