/*
 * This code is generated by blanco Framework.
 */
package blancostruts.runtime.validator;

import java.io.UnsupportedEncodingException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;


/**
 * @author Yasuo Nakanishi
 */
public class DefaultValidator extends AbstractFormValidator {

    private DateFormat _yyyyMmDd = new SimpleDateFormat("yyyyMMdd");
    private DateFormat _yyMmDd = new SimpleDateFormat("yyMMdd");
    private DateFormat _mmDd = new SimpleDateFormat("MMdd");

	public boolean isSupportedFormat(String format) {
        boolean result = false;
        if(format.equals("半角")) {
            result = true;
        } else if(format.equals("全角")) {
            result = true;
        } else if(format.equals("半角数字")) {
            result = true;
        } else if(format.equals("半角英字")) {
            result = true;
        } else if(format.equals("半角英字大文字")) {
            result = true;
        } else if(format.equals("半角英字小文字")) {
            result = true;
        } else if(format.equals("半角英数字")) {
            result = true;
        } else if(format.equals("半角英数字記号")) {
            result = true;
        } else if(format.equals("半角カタカナ")) {
            result = true;
        } else if(format.equals("全角英字大文字")) {
            result = true;
        } else if(format.equals("全角英字小文字")) {
            result = true;
        } else if(format.equals("全角英字")) {
            result = true;
        } else if(format.equals("全角数字")) {
            result = true;
        } else if(format.equals("全角英数字")) {
            result = true;
        } else if(format.equals("全角英数字記号")) {
            result = true;
        } else if(format.equals("全角ひらがな")) {
            result = true;
        } else if(format.equals("全角カタカナ")) {
            result = true;
        } else if(format.equals("全角ひらがなカタカナ")) {
            result = true;
        } else if(format.equals("年月日 (YYYYMMDD)")) {
            result = true;
        } else if(format.equals("年月日 (YYMMDD)")) {
            result = true;
        } else if(format.equals("月日 (MMDD)")) {
            result = true;
        }
        return result;
    }
    
    public boolean dispathFormatValidation(Object value, String format, String name) {
        boolean result = false;
        if(format.equals("半角")) {
            result = validateHalfwidth((String) value);
            if(!result) {
                String key = getMessageKeys().getHalfWidthErrorKey(); 
                Object[] parameters = new Object[]{value, format, name};
                setError(key, parameters);
            }
        } else if(format.equals("全角")) {
            result = validateFullwidth((String) value);
            if(!result) {
                String key = getMessageKeys().getFullWidthErrorKey(); 
                Object[] parameters = new Object[]{value, format, name};
                setError(key, parameters);
            }
        } else if(format.equals("半角数字")) {
            result = validateHalfwidthNumber((String) value);
            if(!result) {
                String key = getMessageKeys().getHalfWidthNumberErrorKey(); 
                Object[] parameters = new Object[]{value, format, name};
                setError(key, parameters);
            }
        } else if(format.equals("半角英字")) {
            result = validateHalfwidthAlphabet((String) value);
            if(!result) {
                String key = getMessageKeys().getHalfWidthAlphabetErrorKey(); 
                Object[] parameters = new Object[]{value, format, name};
                setError(key, parameters);
            }
        } else if(format.equals("半角英字大文字")) {
            result = validateHalfwidthUpperCaseAlphabet((String) value);
            if(!result) {
                String key = getMessageKeys().getHalfWidthUpperCaseAlphabetErrorKey(); 
                Object[] parameters = new Object[]{value, format, name};
                setError(key, parameters);
            }
        } else if(format.equals("半角英字小文字")) {
            result = validateHalfwidthLowerCaseAlphabet((String) value);
            if(!result) {
                String key = getMessageKeys().getHalfWidthLowerCaseAlphabetErrorKey(); 
                Object[] parameters = new Object[]{value, format, name};
                setError(key, parameters);
            }
        } else if(format.equals("半角英数字")) {
            result = validateHalfwidthAlphabetNumber((String) value);
            if(!result) {
                String key = getMessageKeys().getHalfWidthAlphabetNumberErrorKey(); 
                Object[] parameters = new Object[]{value, format, name};
                setError(key, parameters);
            }
        } else if(format.equals("半角英数字記号")) {
            result = validateHalfwidthAlphabetNumberSymbol((String) value);
            if(!result) {
                String key = getMessageKeys().getHalfWidthAlphabetNumberSymbolErrorKey(); 
                Object[] parameters = new Object[]{value, format, name};
                setError(key, parameters);
            }
        } else if(format.equals("半角カタカナ")) {
            result = validateHalfwidthKatakana((String) value);
            if(!result) {
                String key = getMessageKeys().getHalfWidthKatakanaErrorKey(); 
                Object[] parameters = new Object[]{value, format, name};
                setError(key, parameters);
            }
        } else if(format.equals("全角英字大文字")) {
            result = validateFullwidthUpperCaseAlphabet((String) value);
            if(!result) {
                String key = getMessageKeys().getFullWidthUpperCaseAlphabetErrorKey(); 
                Object[] parameters = new Object[]{value, format, name};
                setError(key, parameters);
            }
        } else if(format.equals("全角英字小文字")) {
            result = validateFullwidthLowerCaseAlphabet((String) value);
            if(!result) {
                String key = getMessageKeys().getFullWidthLowerCaseAlphabetErrorKey(); 
                Object[] parameters = new Object[]{value, format, name};
                setError(key, parameters);
            }
        } else if(format.equals("全角英字")) {
            result = validateFullwidthAlphabet((String) value);
            if(!result) {
                String key = getMessageKeys().getFullWidthAlphabetErrorKey(); 
                Object[] parameters = new Object[]{value, format, name};
                setError(key, parameters);
            }
        } else if(format.equals("全角数字")) {
            result = validateFullwidthNumber((String) value);
            if(!result) {
                String key = getMessageKeys().getFullWidthNumberErrorKey(); 
                Object[] parameters = new Object[]{value, format, name};
                setError(key, parameters);
            }
        } else if(format.equals("全角英数字")) {
            result = validateFullwidthAlphabetNumber((String) value);
            if(!result) {
                String key = getMessageKeys().getFullWidthAlphabetNumberErrorKey(); 
                Object[] parameters = new Object[]{value, format, name};
                setError(key, parameters);
            }
        } else if(format.equals("全角英数字記号")) {
            result = validateFullwidthAlphabetNumberSymbol((String) value);
            if(!result) {
                String key = getMessageKeys().getFullWidthAlphabetNumberSymbolErrorKey(); 
                Object[] parameters = new Object[]{value, format, name};
                setError(key, parameters);
            }
        } else if(format.equals("全角ひらがな")) {
            result = validateFullwidthHiragana((String) value);
            if(!result) {
                String key = getMessageKeys().getFullWidthHiraganaErrorKey(); 
                Object[] parameters = new Object[]{value, format, name};
                setError(key, parameters);
            }
        } else if(format.equals("全角カタカナ")) {
            result = validateFullwidthKatakana((String) value);
            if(!result) {
                String key = getMessageKeys().getFullWidthKatakanaErrorKey(); 
                Object[] parameters = new Object[]{value, format, name};
                setError(key, parameters);
            }
        } else if(format.equals("全角ひらがなカタカナ")) {
            result = validateFullwidthKana((String) value);
            if(!result) {
                String key = getMessageKeys().getFullWidthHiraganaKatakanaErrorKey(); 
                Object[] parameters = new Object[]{value, format, name};
                setError(key, parameters);
            }
        } else if(format.equals("年月日 (YYYYMMDD)")) {
            result = validateYYYYMMDD((String) value);
            if(!result) {
                String key = getMessageKeys().getYyyyMmDdErrorKey(); 
                Object[] parameters = new Object[]{value, format, name};
                setError(key, parameters);
            }
        } else if(format.equals("年月日 (YYMMDD)")) {
            result = validateYYMMDD((String) value);
            if(!result) {
                String key = getMessageKeys().getYyMmDdErrorKey(); 
                Object[] parameters = new Object[]{value, format, name};
                setError(key, parameters);
            }
        } else if(format.equals("月日 (MMDD)")) {
            result = validateMMDD((String) value);
            if(!result) {
                String key = getMessageKeys().getMmDdErrorKey(); 
                Object[] parameters = new Object[]{value, format, name};
                setError(key, parameters);
            }
        } else {
            String message = "予期しないフォーマットが渡されました。フォーマット:" + format;
            throw new RuntimeException(message);
        }
        return result;
    }
    
    private String getIlleagalCharactor(String value, String format, String name) {
        StringBuffer sb = new StringBuffer();
        sb.append(name);
        sb.append("に");
        sb.append(format);
        sb.append("以外の文字が渡されました。データ:");
        sb.append(value);
        return sb.toString();
    }
    
    private String getIlleagalDateFormat(String value, String format, String name) {
        StringBuffer sb = new StringBuffer();
        sb.append(name);
        sb.append("に");
        sb.append(format);
        sb.append("不正な日付が渡されました。データ:");
        sb.append(value);
        return sb.toString();
    }

    public boolean validateFormat(Object value, String format, String name) {
		boolean result = false;
        if(!isSupportedFormat(format)) {
            StringBuffer sb = new StringBuffer();
            sb.append("予期しないフォーマットが渡されました。フォーマット:");
            sb.append(format);
            sb.append(", フィールド名称");
            sb.append(name);
            throw new RuntimeException(sb.toString());
        } else if(isEmpty(value)) {
            result = true;
        } else {
            result = dispathFormatValidation(value, format, name);
        }
		return result;
	}

	protected boolean validateHalfwidth(String data) {
		boolean result = false;
        int byteSize = getByteLength(data); 
		result = data.length() == byteSize;
		return result;
	}

	protected boolean validateFullwidth(String data) {
		boolean result = false;
        int byteSize = getByteLength(data); 
		result = data.length() == byteSize / 2;
		return result;
	}
	
	protected int getByteLength(String value) {
		int result = 0;
		try {
			result = value.getBytes("Windows-31J").length;
		} catch (UnsupportedEncodingException e) {
			throw new RuntimeException(e);
		}
		return result;
	}

	protected boolean validateHalfwidthNumber(String value) {
		return !value.matches(".*[\\D]+.*");
	}

	protected boolean validateHalfwidthAlphabet(String value) {
        return !value.matches(".*[^a-zA-Z]+.*");
	}

	protected boolean validateHalfwidthUpperCaseAlphabet(String value) {
        return !value.matches(".*[^A-Z]+.*");
	}

	protected boolean validateHalfwidthLowerCaseAlphabet(String value) {
        return !value.matches(".*[^a-z]+.*");
	}

	protected boolean validateHalfwidthAlphabetNumber(String value) {
        return !value.matches(".*[^a-zA-Z0-9]+.*");
	}

	protected boolean validateHalfwidthAlphabetNumberSymbol(String value) {
        return !value.matches(".*[^\\x20-~]+.*");
	}

	protected boolean validateHalfwidthKatakana(String value) {
        return !value.matches(".*[^\uFF61-\uFF9F]+.*");
	}

	protected boolean validateFullwidthUpperCaseAlphabet(String value) {
        return !value.matches(".*[^\uFF21-\uFF3A]+.*");
	}

	protected boolean validateFullwidthLowerCaseAlphabet(String value) {
        return !value.matches(".*[^\uFF41-\uFF5A]+.*");
	}

	protected boolean validateFullwidthAlphabet(String value) {
        return !value.matches(".*[^\uFF21-\uFF3A\uFF41-\uFF5A]+.*");
	}

	protected boolean validateFullwidthNumber(String value) {
        return !value.matches(".*[^\uFF10-\uFF19]+.*");
	}

	protected boolean validateFullwidthAlphabetNumber(String value) {
        return !value.matches(".*[^\uFF10-\uFF19\uFF21-\uFF3A\uFF41-\uFF5A]+.*");
	}

	protected boolean validateFullwidthAlphabetNumberSymbol(String value) {
        String symbol = "\uFF01-\uFF0F\uFF1A-\uFF20\uFF3B-\uFF40\uFF5B-\uFF5E";
        return !value.matches(".*[^" + symbol + "\uFF10-\uFF19\uFF21-\uFF3A\uFF41-\uFF5A]+.*");
	}

	protected boolean validateFullwidthHiragana(String value) {
        return !value.matches(".*[^\\p{InHiragana}]+.*");
	}

	protected boolean validateFullwidthKatakana(String value) {
        return !value.matches(".*[^\\p{InKatakana}]+.*");
	}

	protected boolean validateFullwidthKana(String value) {
        return !value.matches(".*[^\\p{InHiragana}\\p{InKatakana}]+.*");
	}

	protected boolean validateYYYYMMDD(String value) {
		return checkDate(value, _yyyyMmDd);
	}
    
    private boolean checkDate(String date, DateFormat format) {
        boolean result = true;
        try {
            Date d = format.parse(date);
            Calendar c = new GregorianCalendar();
            c.setTime(d);
            
            if(checkSameDate(date, c, format)) {
                result = true;
            } else {
                result = false;
            }
        } catch (ParseException e) {
            result = false;
        } catch (NumberFormatException nfe) {
            result = false;
        }
        return result;
    }
    
    private boolean checkSameDate(String date, Calendar calendar, DateFormat format) {
        boolean result = true;
        int yyyy = 0;
        int mm = 0;
        int dd = 0;
        if(format.equals(_yyyyMmDd)) {
            yyyy = Integer.parseInt(date.substring(0, 4));
            mm = Integer.parseInt(date.substring(4, 6));
            dd = Integer.parseInt(date.substring(6, 8));
        } else if(format.equals(_yyMmDd)) {
            // TODO もっと詳細に調査する必要がある。
            int y = Integer.parseInt(date.substring(0, 2));
            yyyy = getCentury(y) + y;
            mm = Integer.parseInt(date.substring(2, 4));
            dd = Integer.parseInt(date.substring(4, 6));
        } else if(format.equals(_mmDd)) {         
            yyyy = 1970;
            mm = Integer.parseInt(date.substring(0, 2));
            dd = Integer.parseInt(date.substring(2, 4));
        }
        
        int cYyyy = calendar.get(Calendar.YEAR);
        int cMm = calendar.get(Calendar.MONTH) + 1;
        int cDd = calendar.get(Calendar.DATE);
        
        if(yyyy == cYyyy && mm == cMm && dd == cDd) {
            result = true;
        } else {
            result = false;
        }
        return result;
    }
    
    private int getCentury(int year) {
        int result = 0;
        int nowYear = new GregorianCalendar().get(Calendar.YEAR);
        if(year <= 50) {
            result = nowYear / 100 * 100;
        } else {
            result = (nowYear - 100) / 100 * 100;
        }
        return result;
    }

	protected boolean validateYYMMDD(String value) {
        return checkDate(value, _yyMmDd);
	}

	protected boolean validateMMDD(String value) {
        return checkDate(value, _mmDd);
	}
}
