/*********************************************************************
* All Rights reserved,Copyright (c) K-Opticom
**********************************************************************
*＜プログラム内容＞
*   システム名      ：eo顧客基幹システム
*   モジュール名    ：JZMCreditcardValid
*   ソースファイル名：JZMCreditcardValid.java
*   作成者          ：富士通
*   日付            ：2017年05月22日
*＜機能概要＞
*   クレジットカード番号チェックを行うクラスです。
*＜修正履歴＞
*   バージョン  修正日       修正者      修正内容
*   v3.00.00    2012/04/04   FJ) 日野    新規作成
*   v3.00.00	2012/04/04   FJ) 日野    【ANK-0032-00-00】新規作成
*   v5.00.00	2013/01/23   FJ) 日野    【ANK-1422-00-00】クレジット会社追加
*   v6.00.00	2013/12/26   FJ) 日野    【ANK-1685-00-00】クレジット会社×２社追加
*  v32.00.00	2017/05/22   FJ) 鈴木    【ANK-3156-00-00】クレジットカード番号体系変更対応
*
**********************************************************************/
package eo.common.util;

/**
 * クレジットカード番号チェックを行うクラスです。
 * @author FJ
 */
public class JZMCreditcardValid extends JZMCommonUtil
{

	/** カード種類 JCB */
	private static final String CARD_TYPE_JCB = "00001";

	/** カード種類 VISA */
	private static final String CARD_TYPE_VISA = "00002";

	/** カード種類 MASTER */
	private static final String CARD_TYPE_MASTER = "00003";

	/** カード種類 OMC */
	private static final String CARD_TYPE_OMC = "00004";

	/** カード種類 CF */
	private static final String CARD_TYPE_CF = "00005";

	/** カード種類 イオンクレジット */
	private static final String CARD_TYPE_IEON = "00006";

	/** カード種類 Orico */
	private static final String CARD_TYPE_ORICO = "00008";

	/** カード種類 NICOS */
	private static final String CARD_TYPE_NICOS = "00009";

	/** カード種類 UFJカード  */
	private static final String CARD_TYPE_UFJ = "00010";

	/** カード種類 セゾン */
	private static final String CARD_TYPE_SAISON = "00011";

	/** カード種類 ダイナース */
	private static final String CARD_TYPE_DINERS = "00012";

	/** カード種類 AMEX */
	private static final String CARD_TYPE_AMEX = "00013";

	/** カード種類 UC */
	private static final String CARD_TYPE_UC = "00014";

	/** カード種類 ジャックスカード */
	private static final String CARD_TYPE_JACCS = "00015";

	/** カード種類 ライフカード */
	private static final String CARD_TYPE_LIFE = "00016";

	/** カード種類 TS CUBIC CARD */
	private static final String CARD_TYPE_TS_CUBIC_CARD = "00017";

	/** カード種類 楽天カード */
	private static final String CARD_TYPE_RAKUTEN_CARD = "00018";

	/** カード種類 京阪カード */
	private static final String CARD_TYPE_KEIHAN_CARD = "00019";

	/** カード種類 アプラス */
	private static final String CARD_TYPE_APLUS = "00020";

	/** プレフィックス("35") JCB */
	private static final String[] PREFIX_JCB = {"35"};

	// ▼▼ ANK-3156-00-00 DEL START ▼▼
	//** プレフィックス("4","5") VISA、MASTER */
	//private static final String[] PREFIX_VISA_MASTER = {"4", "5"};

	//** プレフィックス("3","4","5") CF、TS CUBIC CARD、楽天カード */
	//private static final String[] PREFIX_CF_TS_CUBIC_RAKUTEN = {"3", "4", "5"};

	//** プレフィックス("3","4","5","6") イオンクレジット、ジャックスカード、ライフカード */
	//private static final String[] PREFIX_IEON_JACCS_LIFE = {"3", "4", "5", "6"};
	// ▲▲ ANK-3156-00-00 DEL END ▲▲
	
	// ▼▼ ANK-3156-00-00 ADD START ▼▼
	/** プレフィックス("4","5") VISA */
	private static final String[] PREFIX_VISA = {"4", "5"};
	
	/** プレフィックス("2","4","5") MASTER */
	private static final String[] PREFIX_MASTER = {"2","4", "5"};

	/** プレフィックス("2","3","4","5") CF、TS CUBIC CARD、楽天カード */
	private static final String[] PREFIX_CF_TS_CUBIC_RAKUTEN = {"2","3", "4", "5"};

	/** プレフィックス("2","3","4","5","6") イオンクレジット、ジャックスカード、ライフカード */
	private static final String[] PREFIX_IEON_JACCS_LIFE = {"2","3", "4", "5", "6"};
	// ▲▲ ANK-3156-00-00 ADD END ▲▲

	/** プレフィックス("3") DINERS */
	private static final String[] PREFIX_DINERS = {"3"};

	// ▼▼ ANK-3156-00-00 MOD START ▼▼
	//** プレフィックス("4") アプラス */
	/** プレフィックス("4") 京阪 */
	// ▲▲ ANK-3156-00-00 MOD END ▲▲
	private static final String[] PREFIX_KEIHAN = {"4"};
	
	// ▼▼ ANK-3156-00-00 ADD START ▼▼
	/** プレフィックス("2","3") アプラス */
	private static final String[] PREFIX_APLUS = {"2","3"};
	// ▲▲ ANK-3156-00-00 ADD END ▲▲

	/** プレフィックス("34","37") AMEX */
	private static final String[] PREFIX_AMEX = {"34", "37"};
	
	// ▼▼ ANK-3156-00-00 MOD START ▼▼
	//** プレフィックス("45","52") UC */
	//private static final String[] PREFIX_UC = {"45", "52"};
	/** プレフィックス("2","45","52") UC */
	private static final String[] PREFIX_UC = {"2","45", "52"};
	// ▲▲ ANK-3156-00-00 MOD END ▲▲

	/** 桁数(16) デフォルト値 */
	private static final int[] LENGTH_DEFAULT = {16};

	/** 桁数(11, 16) OMC */
	private static final int[] LENGTH_OMC = {11, 16};

	/** 桁数(15, 16) セゾン */
	private static final int[] LENGTH_SAISON = {15, 16};

	/** 桁数(14) ダイナース */
	private static final int[] LENGTH_DINERS = {14};

	/** 桁数(15) AMEX */
	private static final int[] LENGTH_AMEX = {15};

	/**
	 * クレジットカード番号チェックを行います。
	 * <br>
	 * @param creCompany クレジット会社コード
	 * @param cardNo クレジットカード番号
	 * @return boolean チェック結果 true：正常、false：不正
	 */
	public static boolean isCreditcardValid(String creCompany, String cardNo)
	{
		
		// チェック対象となる文字列がnullまたは空文字("")の場合
		if(isNull(creCompany))
		{
			return false;
		}
		if(!isValidCardNo(cardNo))
		{
			return false;
		}
		
		// JCB の場合
		if(CARD_TYPE_JCB.equals(creCompany))
		{
			return checkCardNo(cardNo, PREFIX_JCB, LENGTH_DEFAULT);
		}
		// ▼▼ ANK-3156-00-00 DEL START ▼▼
		// VISA か MASTER の場合
		//else if(CARD_TYPE_VISA.equals(creCompany) || CARD_TYPE_MASTER.equals(creCompany))
		//{
		//	return checkCardNo(cardNo, PREFIX_VISA_MASTER, LENGTH_DEFAULT);
		//}
		// ▲▲ ANK-3156-00-00 DEL END ▲▲
		// ▼▼ ANK-3156-00-00 ADD START ▼▼
		// VISA の場合
		else if(CARD_TYPE_VISA.equals(creCompany))
		{
			return checkCardNo(cardNo, PREFIX_VISA, LENGTH_DEFAULT);
		}
		// MASTER の場合
		else if(CARD_TYPE_MASTER.equals(creCompany))
		{
			return checkCardNo(cardNo, PREFIX_MASTER, LENGTH_DEFAULT);
		}
		// ▲▲ ANK-3156-00-00 ADD END ▲▲
		// OMC の場合
		else if(CARD_TYPE_OMC.equals(creCompany))
		{
			return checkCardNo(cardNo, null, LENGTH_OMC);
		}
		// CF か TS CUBIC CARD か 楽天カード の場合
		else if(CARD_TYPE_CF.equals(creCompany) || CARD_TYPE_TS_CUBIC_CARD.equals(creCompany) || CARD_TYPE_RAKUTEN_CARD.equals(creCompany))
		{
			return checkCardNo(cardNo, PREFIX_CF_TS_CUBIC_RAKUTEN, LENGTH_DEFAULT);
		}
		// イオンクレジット か ジャックスカード か ライフカード の場合
		else if(CARD_TYPE_IEON.equals(creCompany) || CARD_TYPE_JACCS.equals(creCompany) || CARD_TYPE_LIFE.equals(creCompany))
		{
			return checkCardNo(cardNo, PREFIX_IEON_JACCS_LIFE, LENGTH_DEFAULT);
		}
		// Orico か NICOS か UFJカード の場合
		else if(CARD_TYPE_ORICO.equals(creCompany) || CARD_TYPE_NICOS.equals(creCompany) || CARD_TYPE_UFJ.equals(creCompany))
		{
			return checkCardNo(cardNo, null, LENGTH_DEFAULT);
		}
		// セゾン の場合
		else if(CARD_TYPE_SAISON.equals(creCompany))
		{
			return checkCardNo(cardNo, null, LENGTH_SAISON);
		}
		// ダイナース の場合
		else if(CARD_TYPE_DINERS.equals(creCompany))
		{
			return checkCardNo(cardNo, PREFIX_DINERS, LENGTH_DINERS);
		}
		// アメリカンEX の場合
		else if(CARD_TYPE_AMEX.equals(creCompany))
		{
			return checkCardNo(cardNo, PREFIX_AMEX, LENGTH_AMEX);
		}
		// UC の場合
		else if(CARD_TYPE_UC.equals(creCompany))
		{
			return checkCardNo(cardNo, PREFIX_UC, LENGTH_DEFAULT);
		}
		// 京阪カード の場合
		else if(CARD_TYPE_KEIHAN_CARD.equals(creCompany))
		{
			return checkCardNo(cardNo, PREFIX_KEIHAN, LENGTH_DEFAULT);
		}
		// ▼▼ ANK-3156-00-00 MOD START ▼▼
		// アプラス の場合
		//else if(CARD_TYPE_APLUS.equals(creCompany))
		//{
		//	return checkCardNo(cardNo, PREFIX_DINERS, LENGTH_DEFAULT);
		//}
		else if(CARD_TYPE_APLUS.equals(creCompany))
		{
			return checkCardNo(cardNo, PREFIX_APLUS, LENGTH_DEFAULT);
		}
		// ▲▲ ANK-3156-00-00 MOD END ▲▲
		else
		{
			return false;
		}
		
	}
	
	/**
	 * クレジットカード番号チェックを行います。
	 * <br>
	 * @param cardNo クレジットカード番号
	 * @param preArray プレフィックスの配列
	 * @param lenArray 桁数の配列
	 * @return boolean チェック結果 true：正常、false：不正
	 */
	private static boolean checkCardNo(String cardNo, String[] preArray, int[] lenArray)
	{
		for(int len: lenArray)
		{
			if(len == cardNo.length())
			{
				if(preArray == null)
				{
					return true;
				}
				for(String prefix: preArray)
				{
					if(cardNo.startsWith(prefix))
					{
						return true;
					}
				}
			}
		}
		return false;
	}
	
	/**
	 * 有効なクレジットカード番号か判定します。
	 * 文字列に値が設定されていない場合はエラーとします。
	 * また、10桁以下の場合もエラーとします。
	 * <br>
	 * @param cardNo クレジットカード番号
	 * @return boolean チェック結果 true：正常、false：不正
	 */
	private static boolean isValidCardNo(String cardNo)
	{
		if(isNull(cardNo))
		{
			return false;
		}
		if(cardNo.length() < 11)
		{
			return false;
		}
		return true;
	}
}
