package com.dbs.dbsec.util;

import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.view.View;

import androidx.appcompat.app.AppCompatActivity;

import com.dbs.dbsec.R;
import com.dbs.dbsec.activity.ConsentActivity;
import com.dbs.dbsec.activity.LoginActivity;
import com.dbs.dbsec.consent.sign.SignWrapper;
import com.dbs.dbsec.customView.CustomAlertDialog;
import com.dbs.dbsec.customView.NetworkErrorAlert;
import com.dbs.dbsec.httpTask.CallBack;
import com.dbs.dbsec.httpTask.HttpRunnable;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.net.NetworkInterface;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;

public class Common {

  public static void networkErrorAlert(final AppCompatActivity mActivity) {
    final CustomAlertDialog csAlert = new CustomAlertDialog(mActivity);
    csAlert.show();
    csAlert.setContent(mActivity.getString(R.string.networkError), ConsentConfig.ALERT_BTN_TYPE);

    csAlert.btnConfirm2.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
        csAlert.dismiss();
        mActivity.finishAffinity();
      }
    });

  }

  /**
   * 앱 이름을 가져온다
   * @author jksong
   * @Param Context
   * @since 2019-08-08 오후 7:47
   **/
  public static String getAppName(Context mContext) {
    ApplicationInfo applicationInfo = mContext.getApplicationInfo();
    int stringId = applicationInfo.labelRes;
    return stringId == 0 ? applicationInfo.nonLocalizedLabel.toString() : mContext.getString(stringId);
  }
  
  /**
  * Json Parser
  * @author jksong
  * @since 2020-05-12 오후 1:44
  **/
  public static ArrayList<HashMap<String, String>> parseJSON(Context context, String jsonString) {
    ArrayList<HashMap<String, String>> rtn = new ArrayList<HashMap<String, String>>();

    try {
      JSONArray array = new JSONArray(jsonString);

      for(int i = 0; i < array.length(); i++) {
        HashMap<String, String> map = new HashMap<String, String>();

        JSONObject object = array.getJSONObject(i);
        Iterator<?> keys  = object.keys();

        while(keys.hasNext()) {
          String key = (String) keys.next();
          String val = object.getString(key);

          map.put(key, val);
        }

        rtn.add(i, map);

        map = null;
      }
    } catch (JSONException e) {
      e.printStackTrace();
    }

    return rtn;
  }

  /**
   * checkWifi, checkLTE 중 하나라도 연결되어 있으면 네트웍이 가능하다고 판단
   * @author jksong
   * @Param
   * @since 2019-12-05 오전 9:31
   **/
  public static boolean checkNetwork(Context context) {
    boolean rtn = false;

    if(checkLTE(context) || checkWifi(context)) {
      rtn = true;
    } else {
      rtn = false;
    }

    return rtn;
  }

  /**
   * wifi 연결 여부 체크
   * @author jksong
   * @Param
   * @since 2019-12-05 오전 9:30
   **/
  public static boolean checkWifi(Context context) {
    boolean rtn = false;

    ConnectivityManager cm = (ConnectivityManager) context.getSystemService(context.CONNECTIVITY_SERVICE);
    NetworkInfo ni         = cm.getActiveNetworkInfo();

    if(ni != null) {
      if(ni.getType() == ConnectivityManager.TYPE_WIFI) {
        rtn = ni.isConnected();
      }
    }

    return rtn;
  }

  /**
   * 데이터 연결 여부 체크
   * @author jksong
   * @Param
   * @since 2019-12-05 오전 9:31
   **/
  public static boolean checkLTE(Context context) {
    boolean rtn = false;

    ConnectivityManager cm = (ConnectivityManager) context.getSystemService(context.CONNECTIVITY_SERVICE);
    NetworkInfo ni         = cm.getActiveNetworkInfo();

    if(ni != null) {
      if(ni.getType() == ConnectivityManager.TYPE_MOBILE) {
        rtn = ni.isConnected();
      }
    }

    return rtn;
  }

  /**
   * 현재날짜을 가져온다
   * @author jksong
   * @Param
   * @since 2019-06-17 오후 3:49
   **/
  public static int[] toDayDate() {
    Calendar calendar = new GregorianCalendar(Locale.KOREA);
    int nYear = calendar.get(Calendar.YEAR);
    int nMonth = calendar.get(Calendar.MONTH) + 1;
    int nDay = calendar.get(Calendar.DAY_OF_MONTH);

    int toDayDate[] = {nYear, nMonth, nDay};
//    String toDayDate[] = {String.valueOf(nYear), String.valueOf(nMonth), String.valueOf(nDay)};
    return toDayDate;
  }

  /**
   * DeviceMacAddress 가져오기
   * @author jksong
   * @Param
   * @since 2019-08-22 오후 8:37
   **/
  public static String getMACAddress() {
    try {
      List<NetworkInterface> interfaces = Collections.list(NetworkInterface.getNetworkInterfaces());
      for (NetworkInterface intf : interfaces) {
        if (!intf.getName().equalsIgnoreCase("wlan0")) continue;
        byte[] mac = intf.getHardwareAddress();
        if (mac==null) return "";
        StringBuilder buf = new StringBuilder();
        for (int idx=0; idx<mac.length; idx++)
          buf.append(String.format("%02X:", mac[idx]));
        if (buf.length()>0) buf.deleteCharAt(buf.length()-1);
        return buf.toString();
      }
    } catch (Exception ex) { } // for now eat exceptions
    return "";
  }
//  String macAddress = getMACAddress("wlan0");

  public static String nowDate() {
    SimpleDateFormat format = new SimpleDateFormat ( "yyyy/MM/dd");
    Date date = new Date();
    String strDate = format.format(date);
    return strDate;
  }

  public static String logTime() {
    SimpleDateFormat format = new SimpleDateFormat ( "yyyy-MM-dd HH:mm:ss");
    Date date = new Date();
    String strDate = format.format(date);
    return strDate;
  }

  /**
   * 시간 더하기 빼기
   * @author jksong
   * @Param
   * @since 2019-08-30 오후 2:35
   **/
  public static String addDate(String fromDate, String format, int addYear, int addMonth, int addDate, int addHour, int addMinute) {

    SimpleDateFormat sdf = new SimpleDateFormat(format);
    Date date = null;
    try {
      date = sdf.parse(fromDate);

      Calendar cal = new GregorianCalendar();

      cal.setTime(date);
      cal.add(Calendar.YEAR, +addYear);
      cal.add(Calendar.MONTH, +addMonth);
      cal.add(Calendar.DATE, +addDate);
      cal.add(Calendar.HOUR, +addHour);
      cal.add(Calendar.MINUTE, +addMinute);
//    cal.add(Calendar.SECOND, +addSecond);

      SimpleDateFormat sdf2 = new SimpleDateFormat(format);
      String toDate = sdf2.format(cal.getTime());

      return toDate;
    } catch (ParseException e) {
      e.printStackTrace();
    }

    return "";
  }

  /**
   * 문자열에 / (슬러쉬)를 제거한다
   * @author jksong
   * @Param
   * @since 2019-08-12 오전 9:00
   **/
  public static String removeSlashStr(String str) {
    str = str.replace("/", "");
    return str;
  }

  /**
   * 날짜 포맷에 / (슬러쉬)를 추가한다
   * @author jksong
   * @Param
   * @since 2019-12-05 오전 9:33
   **/
  public static String addSlashDate(String dateStr) {
    String resDate = "";
    try {
      SimpleDateFormat df = new SimpleDateFormat("yyyymmdd");
      Date date = df.parse(dateStr);
      SimpleDateFormat df1 = new SimpleDateFormat("yyyy/mm/dd");
      resDate = df1.format(date);
    } catch (ParseException e) {
      e.printStackTrace();
    }

    return resDate;
  }

  /**
   * 한자리 숫자 일때 앞에 0을 붙여준다
   * @author jksong
   * @Param integer
   * @since 2019-06-17 오후 3:50
   **/
  public static String plusZero(int num) {
    int temp = num;
    int length = (int) (Math.log10(temp) + 1);
    String d = "";

    if (length == 1) {
      d = String.format("%02d", temp);
    } else {
      d = String.valueOf(temp);
    }

    return d;
  }

  /**
   * SharedPreferences String type data 저장
   * @author jksong
   * @Param Context, 저장될 타입, key, value
   * @since 2019-08-08 오후 7:47
   **/
  public static void setStringPreference(Context context, String type, String key, String value) {
    SharedPreferences prefs = context.getSharedPreferences(type, context.MODE_PRIVATE);
    SharedPreferences.Editor editor = prefs.edit();
    editor.putString(key, value);
    editor.commit();
  }

  /**
   * SharedPreferences String type data 가져오기
   * @author jksong
   * @Param Context, 저장했던 타입, key
   * @since 2019-08-08 오후 7:47
   **/
  public static String getStringPreference(Context context, String type, String key) {
//    SharedPreferences prefs = context.getSharedPreferences(type, context.MODE_MULTI_PROCESS);
    SharedPreferences prefs = context.getSharedPreferences(type, context.MODE_PRIVATE);
    String rtn = prefs.getString(key, "");

    return rtn;
  }

  /**
   * SharedPreferences 저장한 타입을 모두 제거
   * @author jksong
   * @Param Context, 저장한 type
   * @since 2019-08-08 오후 7:47
   **/
  public static void clearPreference(Context context, String type) {
//    SharedPreferences prefs = context.getSharedPreferences(type, context.MODE_MULTI_PROCESS);
    SharedPreferences prefs = context.getSharedPreferences(type, context.MODE_PRIVATE);
    SharedPreferences.Editor editor = prefs.edit();
    editor.clear();
    editor.commit();
  }

  /**
   * 루팅방지 코드
   * @author jksong
   * @since 2020-03-05 오전 9:39
   **/
  public static boolean checkSuperUser(Context context) {
    return (checkRootedFiles(context) == true || checkSuperUserCommand(context) == true  || checkSuperUserCommand2(context) == true ||  checkTags(context) == true) ? true : false;
  }

  private static boolean checkRootedFiles(Context context){
    final String[] files = context.getResources().getStringArray(R.array.TEST_PATH);

    for(int i = 0; i<files.length; i++){
      File file = new File(files[i]);
      if(null != file && file.exists()){
        return true;
      }
    }
    return false;
  }

  private static boolean checkTags(Context context) {
    String buildTags = android.os.Build.TAGS;
    if (buildTags != null && buildTags.contains(context.getString(R.string.key))) {
      return true;
    }
    return false;
  }

  private static boolean checkSuperUserCommand(Context context){
    try {
      Runtime.getRuntime().exec(context.getString(R.string.user));
      return true;
    } catch (Error e){
    } catch (Exception e){
    }
    return false;
  }

  private static boolean checkSuperUserCommand2(Context context) {
    Process process = null;
    try {
      process = Runtime.getRuntime().exec(new String[] {context.getString(R.string.tempPath), context.getString(R.string.user)});
      BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));
      if (in.readLine() != null) return true;
      return false;
    } catch (Throwable t) {
      return false;
    } finally {
      if (process != null) process.destroy();
    }
  }

  /**
   * sha256 passwd encrypt
   * @author jksong
   * @Param
   * @since 2019-08-08 오후 7:47
   **/
  public static String sha256Encrypt(String str) {
    String SHA = "";

    try {
      MessageDigest sh = MessageDigest.getInstance("SHA-256");
      sh.update(str.getBytes());
      byte byteData[] = sh.digest();
      StringBuffer sb = new StringBuffer();

      for (int i = 0; i < byteData.length; i++) {
        sb.append(Integer.toString((byteData[i] & 0xff) + 0x100, 16).substring(1));
      }

      SHA = sb.toString();

    } catch (NoSuchAlgorithmException e) {
      e.printStackTrace();
      SHA = null;
    }

    return SHA;
  }

  /**
   * api 호출시 세션시간을 검사
   * @author jksong
   * @Param
   * @since 2019-12-05 오전 9:34
   **/
  public static boolean sessionTimeCheck(final Context context) {
    try {
      SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmm");
      String saveTime = Common.getStringPreference(context, "sessionTime", "sessionTime");
      Date nowDate = new Date();
      String sessionEndTime = dateFormat.format(nowDate);
      int sessionTime = Integer.parseInt(ConsentConfig.SETTING_DATA.get("SESSION_TIME")) == 0 ? 30 : Integer.parseInt(ConsentConfig.SETTING_DATA.get("SESSION_TIME"));
//      int sessionTime = 30;

      String addDateTime = Common.addDate(saveTime, "yyyyMMddHHmm", 0, 0, 0, 0, sessionTime);
      Date saveDateTime = dateFormat.parse(addDateTime);

      Date sessionEndDateTime = dateFormat.parse(sessionEndTime);

      if (saveDateTime.getTime() < sessionEndDateTime.getTime()) {
        final ConsentActivity instance = ((ConsentActivity) context);
        instance.csAlert.show();
        instance.csAlert.setContent(context.getString(R.string.sessionTimeOut), ConsentConfig.ALERT_BTN_TYPE);
        instance.csAlert.btnConfirm2.setOnClickListener(new View.OnClickListener() {
          @Override
          public void onClick(View v) {
//            SignWrapper.getInstance().deleteAll();
            Common.clearPreference(context, "userInfo");
            Common.clearPreference(context, "sessionTime");

            instance.csAlert.dismiss();

            Intent intent = new Intent(context, LoginActivity.class);
            context.startActivity(intent);
            instance.finish();
          }
        });

        return false;
      } else {
        Common.setStringPreference(context, "sessionTime", "sessionTime", sessionEndTime);
        return true;
      }

    } catch (ParseException e) {
      e.printStackTrace();
      return false;
    }

  }

  public static void callHttp(Context context, String url, HashMap<String, String> mData, CallBack callback) {
    if (sessionTimeCheck(context) == true) {
      if (checkNetwork(context) == true) {

        HttpRunnable runnable = new HttpRunnable(url, mData, callback);
        Thread thread = new Thread(runnable);
        thread.start();
      } else {
        ((ConsentActivity) context).dismissProgress();
        NetworkErrorAlert networkErrorAlert = new NetworkErrorAlert(context);
        networkErrorAlert.show();
      }
    }
  }
}
