package org.itscool.commons.util;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 文字列の妥当性チェックを行うユーティリティクラスです
 * @author kanou
 */
public class InputCheckUtil {
    /**
     * パラメータがnullもしくは空文字でないことを検証します
     * @param paramValue パラメータを指定します
     * @return 検証が正しい場合はtrueを返します
     */
    public static boolean isNotNull(String paramValue){
        boolean ret = true;
        
        if( paramValue == null || paramValue.toString().length() == 0){
            ret = false;
        }
        
        return ret;
    }
    
    /**
     * 全角チェック<br>
     * 引数で与えられた文字列が、全て全角であるかどうかをチェック
     * するメソッドです。<br>
     *
     * 全て全角の場合は true 、全角以外が存在する場合は false を返します。<br>
     * @param str 入力データ
     * @return 指定されたデータが条件にマッチする場合はtrueを返します
     */
    public static boolean checkFullSize(String str) {
        byte []bytes;
        if( str == null ) return false;
        
        bytes = str.getBytes();
        
        // lengthを２倍する
        int beams = str.length() * 2;
        
        int enterCounter = 0;
        
        StringBuffer sb = new StringBuffer(str);
        
        for (int i=0; i < str.length(); i++) {
            // 改行コードは対象外とする
            if ('\n' == sb.charAt(i)) {
                beams = beams - 2;
            }
        }
        
        // lengthの２倍とバイト数が異なる場合は半角が含まれている
        if (beams != bytes.length) {
            return false;
        }
        
        return true;
    }
    
    /**
     * 半角チェック<br>
     * 引数で与えられた文字列が、全て半角であるかどうかを
     * チェックするメソッドです。<br>
     * 全て半角の場合は true 、半角以外が存在する場合は false を返します。<br>
     * @param str 入力データ
     * @return 指定されたデータが条件にマッチする場合はtrueを返します
     */
    public static boolean checkHalfSize(String str) {
        byte [] bytes;
        if(!checkRequerd(str)) return false;
        
        bytes = str.getBytes();
        
        int beams = str.length();
        int enterCounter = 0;
        
        StringBuffer sb = new StringBuffer(str);
        
        for (int i=0; i < str.length(); i++) {
            //改行コードは対象外とする
            if ('\n' == sb.charAt(i)) {
                beams = beams - 2;
            }
//	        //半角スペースは対象外とする
//	        else if(' ' == sb.charAt(i)){
//	        	beams = beams - 2;
//	        }
        }
        
        //lengthとバイト数が異なる場合は全角が含まれている
        if (beams != bytes.length) {
            return false;
        }
        
        return true;
    }
    
    /**
     * 半角数字チェック<br>
     * 引数で与えられた文字列が、全て半角数字であるかどうかを
     * チェックするメソッドです。<br>
     * 全て半角数字の場合は true 、半角数字以外が存在する場合は false を返します。
     * @param str 入力データ
     * @return 指定されたデータが条件にマッチする場合はtrueを返します
     */
    public static boolean checkDigit(String input) {
        if(!checkRequerd(input)) return false;
        
        for (int i = 0; i < input.length(); i++) {
            char c = input.charAt(i);
            
            if ( (c < '0' || c > '9') ) {
                //数字でない
                return false;
            }
        }
        
        return true;
    }
    
    /**
     * 半角英字チェック<br>
     * 引数で与えられた文字列が、全て半角英字であるかどうかを
     * チェックするメソッドです。<br>
     * 全て半角英字の場合は true 、半角英字以外が存在する場合は false を返します。
     * @param input 入力文字列
     * @return 半角英字の場合はtrueを返します
     */
    public static boolean checkAlphabet(String input) {
        if(!checkRequerd(input)) return false;
        
        for (int i = 0; i < input.length(); i++) {
            char c = input.charAt(i);
            if ( (c < 'a' || c > 'z') &&        //小文字アルファベットでない
                (c < 'A' || c > 'Z') ) {       //大文字アルファベットでない
                //半角スペースは対象外
                if( c == ' '){
                    continue;
                }
                return false;
            }
        }
        
        return true;
    }
    
    /**
     * 小文字半角英字チェック<br>
     * 引数で与えられた文字列が、全て小文字半角英字であるかどうかを
     * チェックするメソッドです。<br>
     * 全て半角英字の場合は true 、半角英字以外が存在する場合は false を返します。
     * @param input 入力文字列
     * @return 半角英字の場合はtrueを返します
     */
    public static boolean checkSmallAlphabet(String input) {
        if(!checkRequerd(input)) return false;
        
        for (int i = 0; i < input.length(); i++) {
            char c = input.charAt(i);
            if ( (c < 'a' || c > 'z')){        //小文字アルファベットでない
                //半角スペースは対象外
                if( c == ' '){
                    continue;
                }
                return false;
            }
        }
        
        return true;
    }
    
    /**
     * 大文字半角英字チェック<br>
     * 引数で与えられた文字列が、全て大文字半角英字であるかどうかを
     * チェックするメソッドです。<br>
     * 全て半角英字の場合は true 、半角英字以外が存在する場合は false を返します。
     * @param input 入力文字列
     * @return 半角英字の場合はtrueを返します
     */
    public static boolean checkLargeAlphabet(String input) {
        if(!checkRequerd(input)) return false;
        
        for (int i = 0; i < input.length(); i++) {
            char c = input.charAt(i);
            if ( (c < 'A' || c > 'Z') ) {       //大文字アルファベットでない
                //半角スペースは対象外
                if( c == ' '){
                    continue;
                }
                return false;
            }
        }
        
        return true;
    }
    
    /**
     * 半角英数チェック<br>
     * 引数で与えられた文字列が、全て半角英数であるかどうかを
     * チェックするメソッドです。<br>
     * 全て半角英数の場合は true 、半角英数以外が存在する場合は false を返します。
     * @param input 入力データ
     * @return 指定されたデータが条件にマッチする場合はtrueを返します
     */
    public static boolean checkDigitAlphabet(String input) {
        if(!checkRequerd(input)) return false;
        
        for (int i = 0; i < input.length(); i++) {
            char c = input.charAt(i);
            if ( (c < '0' || c > '9') &&        //数字でない
                (c < 'a' || c > 'z') &&        //小文字アルファベットでない
                (c < 'A' || c > 'Z') ) {       //大文字アルファベットでない
                //半角スペースは対象外
                if( c == ' '){
                    continue;
                }
                return false;
            }
        }
        
        return true;
    }
    
    /**
     * 半角カナチェック<br>
     * 引数で与えられた文字列が、全て半角カナであるかどうかを
     * チェックするメソッドです。<br>
     * 全て半角カナの場合は true 、半角カナ以外が存在する場合は false を返します。
     * @param input 入力データ
     * @return 指定されたデータが条件にマッチする場合はtrueを返します
     */
    public static boolean checkHankakuKana(String input) {
        if(!checkRequerd(input)) return false;
        
        final String HANKAKU_KANA = "ｱｲｳｴｵｶｷｸｹｺｻｼｽｾｿ" +
            "ﾀﾁﾂﾃﾄﾅﾆﾇﾈﾉﾊﾋﾌﾍﾎﾏﾐﾑﾒﾓﾔﾕﾖﾗﾘﾙﾚﾛﾜｦﾝｧｨｩｪｫｯｬｭｮﾞﾟｰ､｡｢｣･";
        
        for (int i = 0; i < input.length(); i++) {
            char c = input.charAt(i);
            
            if ( -1 == HANKAKU_KANA.indexOf( ( int ) c ) ) {
                return false;
            }
        }
        
        return true;
    }
    
    /**
     * 文字の桁数チェック<br>
     * 引数で与えられた文字列が、指定された桁数の範囲内であるかどうかを
     * チェックするメソッドです。<br>
     * 桁数はバイト数でチェックされ、範囲内の場合は true 、範囲外の場合は false を返します。
     * @param val データ
     * @param min 最小桁数
     * @param max 最大桁数
     * @return 指定されたデータが条件にマッチする場合はtrueを返します
     */
    public static boolean checkStrLength( String val, int min, int max){
        if(!checkRequerd(val)) return false;
        
        int strlen = 0;
        
        if ( val == null ) {
            return false;
        }
        
        strlen = val.getBytes().length;
        
        if ( strlen < min || strlen > max ) {
            return false;
        }
        
        return true;
    }
    
    /**
     * 数値の桁数チェック<br>
     * 引数で与えられた文字列が、指定された桁数の範囲内であるかどうかを
     * チェックするメソッドです。<br>
     * 桁数はバイト数でチェックされ、範囲内の場合は true 、範囲外の場合は false を返します。
     * @param str データ
     * @param min 最小桁数
     * @param max 最大桁数
     * @return 指定されたデータが条件にマッチする場合はtrueを返します
     */
    public static boolean checkDigitLength( String str, double min, double max){
        if(!checkRequerd(str)) return false;
        
        double value;
        try{
            value = Double.parseDouble(str);
        }catch(Exception e){
            return false;
        }
        if(min <= value && value <= max){
            return true;
        }else{
            return false;
        }
    }
    
    /**
     * 必須チェック<br>
     * @param str 入力データ
     * @return 指定されたデータが条件にマッチする場合はtrueを返します
     */
    public static boolean checkRequerd(String str){
        if(str==null || str.length()==0){
            return false;
        }else{
            return true;
        }
    }
    
    /**
     * 電話番号チェック
     * @param data 入力データ
     * @return 指定されたデータが条件にマッチする場合はtrueを返します
     */
    public static boolean checkTelNo(String data){
        if(!checkRequerd(data)) return false;
        
        String koubun = "\\d{1,4}?-\\d{1,4}?-\\d{1,4}";
        Pattern pattern = Pattern.compile(koubun);
        Matcher matcher = pattern.matcher(data);
        boolean b= matcher.matches();
        
        return true;
    }
    
    /**
     * メールアドレスチェック
     * @param data 入力データ
     * @return 指定されたデータが条件にマッチする場合はtrueを返します
     */
    public static boolean checkMailAddr(String data){
        if(!checkRequerd(data)) return false;
        
        String koubun = "[!#-9A-~]+@[a-z0-9-_]+\\.+[a-z0-9-_]+\\.+[a-z0-9-]";
        Pattern pattern = Pattern.compile(koubun);
        Matcher matcher = pattern.matcher(data);
        boolean b= matcher.matches();
        
        return true;
    }
    
    /**
     * 郵便番号チェック
     * @param data 入力データ
     * @return 指定されたデータが条件にマッチする場合はtrueを返します
     */
    public static boolean checkPostCode(String data){
        if(!checkRequerd(data)) return false;
        
        String koubun = "\\d{3}-\\d{4}";
        Pattern pattern = Pattern.compile(koubun);
        Matcher matcher = pattern.matcher(data);
        boolean b= matcher.matches();
        
        return true;
    }
    
    /**
     * URLチェック
     * 「http://」は「http://」ではじまることを表します。
     * 「\w」はA?Zを表します。
     * 「\d」は0?9を表します。
     * 「[\w\d/%#$&?()~_.=+-]」は[]内のいずれかの文字を表します。
     * 「+」がつくと、前述の文字が1つ以上続くことを表します。
     *
     * @param data 入力データ
     * @return 指定されたデータが条件にマッチする場合はtrueを返します
     */
    public static boolean checkUrl(String data){
        if(!checkRequerd(data)) return false;
        
        String koubun = "http://[\\w\\d/%#$&?()~_.=+-]+";
        Pattern pattern = Pattern.compile(koubun);
        Matcher matcher = pattern.matcher(data);
        boolean b= matcher.matches();
        
        return true;
    }
}
