/*
 * COPYRIGHT (c) 2018 All rights reserved by HANWHA LIFE.
 */
package kr.co.zumo.app.lifeplus.util;

import android.os.Build;
import android.support.annotation.Nullable;
import android.telephony.PhoneNumberUtils;
import android.text.Html;
import android.text.Spanned;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Locale;

/**
 * String 관련 유틸리티 클래스
 * <pre>
 * </pre>
 *
 * @author 민효동
 * @version 1.0
 * @history 민효동   [2018. 9. 11.]   [최초 작성]
 * @since 2018. 9. 11.
 */
public class StringUtil {

  /**
   * 문자열이 있는지 확인
   *
   * @param str null|"apple"
   * @return false|true
   */
  public static boolean isFull(@Nullable String str) {
    return isEmpty(str) == false;
  }

  /**
   * null or "" 인지 확인
   *
   * @param str null|"apple"
   * @return true|false
   */
  public static boolean isEmpty(@Nullable String str) {
    return str == null || str.length() == 0;
  }

  /**
   * 이메일 주소 규칙 검사
   *
   * @param email asdf@gmail.com
   * @return true: 이메일 규격 맞음
   */
  public static boolean isValidEmail(String email) {
    return isFull(email) && email.matches("[a-zA-Z0-9\\+\\.\\_\\%\\-\\+]{1,256}" + "\\@" + "[a-zA-Z0-9][a-zA-Z0-9\\-]{0,64}" + "(" + "\\." + "[a-zA-Z0-9][a-zA-Z0-9\\-]{0,25}" + ")+");
  }

  /**
   * 유효한 패스워드인지 검사
   * - 8자 이상, 영소문자, 대문자, 숫자, 특수문자 모두 포함
   * - 지원 특수 문자 : #?!@$%^&*0()-+=_~`
   *
   * @param password asdf|1!aw35rtaeQ
   * @return false|true
   */
  public static boolean isValidPassword(String password) {
    return isFull(password) && password.matches("^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*0()-+=_~`]).{8,}$");
  }


  /**
   * 왼쪽을 0으로 채워서 length 길이의 문자열 만들기
   *
   * @param length       4
   * @param numberString 7
   * @return 0007
   */
  public static String lpad(int length, String numberString) {
    if (isEmpty(numberString)) {
      numberString = "0";
    }

    numberString = numberString.trim();
    if (isEmpty(numberString)) {
      numberString = "0";
    }

    try {
      int number = Integer.valueOf(numberString);
      return String.format("%0" + length + "d", number);
    } catch (Exception e) {
      return numberString;
    }
  }

  /**
   * 왼쪽을 0으로 채워서 length 길이의 문자열 만들기
   *
   * @param length 4
   * @param number 7
   * @return 0007
   */
  public static String lpad(int length, int number) {
    return lpad(length, String.valueOf(number));
  }

  private static String convertToHex(byte[] data) {
    StringBuilder buf = new StringBuilder();
    for (byte b : data) {
      int halfByte = (b >>> 4) & 0x0F;
      int twoHalf = 0;
      do {
        buf.append((0 <= halfByte) && (halfByte <= 9) ? (char) ('0' + halfByte) : (char) ('a' + (halfByte - 10)));
        halfByte = b & 0x0F;
      } while (twoHalf++ < 1);
    }
    return buf.toString();
  }

  /**
   * 암호화 - SHA-1
   *
   * @param text "8364"
   * @return
   * @throws NoSuchAlgorithmException
   * @throws UnsupportedEncodingException
   */
  public static String convertToSHA1(String text) throws NoSuchAlgorithmException, UnsupportedEncodingException {
    MessageDigest md = MessageDigest.getInstance("SHA-1");
    byte[] textBytes = text.getBytes("iso-8859-1");
    md.update(textBytes, 0, textBytes.length);
    byte[] sha1hash = md.digest();
    return convertToHex(sha1hash);
  }

  /**
   * 암호화 - MD5
   *
   * @param str "3245"
   * @return
   */
  public static String convertToMD5(String str) throws NoSuchAlgorithmException {
    MessageDigest md = MessageDigest.getInstance("MD5");
    return convertTo(md, str);
  }

  /**
   * 암호화 - SHA-256
   *
   * @param str "3245"
   * @return
   */
  public static String convertToSHA256(String str) throws NoSuchAlgorithmException {
    MessageDigest sh = MessageDigest.getInstance("SHA-256");
    return convertTo(sh, str);
  }

  private static String convertTo(MessageDigest messageDigest, String str) {
    String encryptedString = "";
    messageDigest.update(str.getBytes());
    byte[] bytes = messageDigest.digest();
    StringBuffer sb = new StringBuffer();
    for (byte byteData : bytes) {
      sb.append(Integer.toString((byteData & 0xff) + 0x100, 16).substring(1));
    }
    encryptedString = sb.toString();
    return encryptedString;
  }

  /**
   * url 의 프로토콜 인식 문자열 (http://, https:// 를 제거한다.
   *
   * @param url
   * @return
   */
  public static String removeProtocol(String url) {
    return url.replaceAll("^http[s]?://", "");
  }

  /**
   * 문자열 중 숫자만 남기고 반환한다.
   *
   * @param stringForNumber "345AD93"
   * @return "34593"
   */
  public static String getPureNumber(String stringForNumber) {
    return stringForNumber.replaceAll("[^0-9]", "");
  }

  /**
   * HTML 이 적용된 Spanned 반환
   *
   * @param str
   * @return
   */
  public static Spanned fromHtml(String str) {
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
      return Html.fromHtml(str, Html.FROM_HTML_MODE_LEGACY);
    }
    else {
      return Html.fromHtml(str);
    }
  }

  /**
   * 폰 번호 스타일 반환 (국내 전용)
   *
   * @param phoneNumber 01037037037, 0112345678
   * @return 010-3703-7037, 011-234-5678
   */
  public static String formatPhoneNumber(String phoneNumber) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
      phoneNumber = PhoneNumberUtils.formatNumber(phoneNumber, Locale.KOREA.getCountry());
    }
    else {
      phoneNumber = PhoneNumberUtils.formatNumber(phoneNumber);
    }

    return phoneNumber;
  }
}
