using System;
using System.IO;
using System.Security.Cryptography;
using System.Windows.Forms;
//using KMCLIENTAXLib;
using ClipSoft.eForm.Base.Dialog;

namespace CLIP.eForm.Consent.UI {
  class SignatureConfig {
    //KMClientAX kmiAx = new KMClientAX();
    KMCLIENTAXLib.KMClientAX kmiAx = new KMCLIENTAXLib.KMClientAX();
    SKCOMMAXLib.SKCommAX CertManX = new SKCOMMAXLib.SKCommAX();

    public void SignAllClear() {
      try {
        int nRet;

        /*
         * 특정 DN 체계를 가진 인증서를 일괄 삭제 합니다.
         */
        //nRet = kmiAx.CertBatchDel("ou=EMR,ou=대구파티마병원,ou=의료,o=SignKorea,c=KR");
        nRet = kmiAx.CertBatchDel("ou=EMR,ou=경북대학교병원,ou=의료,o=SignKorea,c=KR");
        nRet = kmiAx.CertBatchDel("ou=EMR,ou=칠곡경북대학교병원,ou=의료,o=SignKorea,c=KR");
        //if (nRet == 0)
        //{
        //    MessageBoxDlg.Show(true, "로컬 PC 인증서 일괄 삭제 실패-" + kmiAx.Error_MSG()
        //                        , string.Format(Properties.Resources.msg_caption_confirm)
        //                        , MessageBoxButtons.OK, MessageBoxIcon.Information);
        //}

      }
      catch(Exception ex) {
        MessageBoxDlg.Show(true, "인증서 삭제 실패 " + ex
                            , string.Format(Properties.Resources.msg_caption_confirm)
                            , MessageBoxButtons.OK, MessageBoxIcon.Information);
      }
    }

    public string SetSignServerInfo(string ip, int port, string id) {
      try {
        int nRet;
        string strRet;

        SignAllClear();
        nRet = kmiAx.kmsConnect(ip, Convert.ToInt32(port));
        if(nRet == 0) {
          MessageBoxDlg.Show(true, "kmi 서버 접속 실패-" + kmiAx.Error_MSG()
                              , string.Format(Properties.Resources.msg_caption_confirm)
                              , MessageBoxButtons.OK, MessageBoxIcon.Information);
          return string.Format("{0}", nRet);
        }

        strRet = kmiAx.kmsInit();
        if(strRet == "") {
          MessageBoxDlg.Show(true, "kmi 초기화 실패-" + kmiAx.Error_MSG()
                              , string.Format(Properties.Resources.msg_caption_confirm)
                              , MessageBoxButtons.OK, MessageBoxIcon.Information);
          kmiAx.kmsDisconnect();
          return "-1";
        }

        strRet = kmiAx.GetKeyAndCert(id);
        if(strRet == "") {
          MessageBoxDlg.Show(true, "인증서 다운로드 실패" + kmiAx.Error_MSG()
                              , string.Format(Properties.Resources.msg_caption_confirm)
                              , MessageBoxButtons.OK, MessageBoxIcon.Information);
          kmiAx.kmsDisconnect();
          return "-1";
        }

        kmiAx.kmsDisconnect();

        return strRet;
      }
      catch(Exception ex) {
        MessageBoxDlg.Show(true, "인증서 다운로드 실패 " + ex
                            , string.Format(Properties.Resources.msg_caption_confirm)
                            , MessageBoxButtons.OK, MessageBoxIcon.Information);
        return "-1";
      }
    }

    public string SignatureExec(string sCertTarget, string dn, string userName, string userId, bool dualViewer) {
      try {
        int i = 0;
        //bool checkState = true;

        //BSTR pszUserID : 인증서 DN 또는 DN의 userid
        //BSTR pszSuffix: 검색할 인증서의 DN suffix(예: ou = test,O = test,c = KR )
        //BSTR pszPassword : 인증서 비밀번호
        //long Type : 인증서 선택/ 나열 방법을 정의

        //string singKoreaDn = CertManX.SetMatchedContextExt("", "", "", 256 + 0 + 1);
        //if (!dn.Equals(singKoreaDn))
        //{
        //    // 공인인증서 초기화
        //    CertManX.UnsetMatchedContext();
        //    checkState = false;
        //}

        //if(!checkState)
        //{
        // 공인인증서 초기화
        int passwordLimitcnt = 5;
        CertManX.UnsetMatchedContext();//암호를 새로 물음
        CertManX.SetWrongPasswordLimit(passwordLimitcnt);

        // 비밀번호 입력
        string sPassword = string.Empty;
        SignaturePasswordForm signPasswordForm = new SignaturePasswordForm(userName, userId, dualViewer);
        if(signPasswordForm.ShowDialog() == DialogResult.OK) {
          sPassword = signPasswordForm.GetPassword();
          signPasswordForm.Close();
        }

        if(string.IsNullOrEmpty(sPassword)) {
          return "-50";
        }

        bool passwordState = false;
        for(int j = 0; j < passwordLimitcnt; j++) {
          //if (CertManX.SetMatchedContextExt(dn, "ou=EMR,ou=대구파티마병원,ou=의료,o=SignKorea,c=KR", sPassword, 256 + 0 + 1) == null)
          if(CertManX.SetMatchedContextExt(dn, "", sPassword, 256 + 0 + 1) == null) {
            if(CertManX.GetLastErrorCode() == 2417) {
              i++;
              MessageBoxDlg.Show(true, "비밀번호 오류 : " + i + "회"
                              , string.Format(Properties.Resources.msg_caption_confirm)
                              , MessageBoxButtons.OK, MessageBoxIcon.Information);

              sPassword = string.Empty;

              if(i < passwordLimitcnt) {
                signPasswordForm = new SignaturePasswordForm(userName, userId, dualViewer);
                if(signPasswordForm.ShowDialog() == DialogResult.OK) {
                  sPassword = signPasswordForm.GetPassword();
                  signPasswordForm.Close();
                }

                if(string.IsNullOrEmpty(sPassword)) {
                  return "-50";
                }
              }
            }
          }
          else {
            passwordState = true;
            break;
          }

          CertManX.UnsetMatchedContext();//암호를 새로 물음
        }

        // 공인인증서 비밀번호 입력 최종 실패시 리턴
        if(!passwordState) {
          return "-50";
        }

        i = 0;

        string plain;
        plain = sCertTarget;
        string signdata = CertManX.SignDataB64("", plain, 0);
        if(signdata == null) {
          MessageBoxDlg.Show(true, "SignDataB64 실패 : [" + CertManX.GetLastErrorCode() + "]" + CertManX.GetLastErrorMsg()
                              , string.Format(Properties.Resources.msg_caption_confirm)
                              , MessageBoxButtons.OK, MessageBoxIcon.Information);
          return "-50";
        }

        return signdata;
      }
      catch(Exception ex) {
        MessageBoxDlg.Show(true, "인증서 실행 실패 " + ex
                            , string.Format(Properties.Resources.msg_caption_confirm)
                            , MessageBoxButtons.OK, MessageBoxIcon.Information);
        return "-1";
      }
    }

    public string getSHA256ImageHash(String fileList, string delimiter) {
      byte[] hashValue;
      string hashStr = string.Empty;
      try {
        string[] sFullPath = fileList.Split('^');

        if(sFullPath != null && sFullPath.Length > 0) {
          FileStream fileStream = null;
          SHA256 mySHA256 = SHA256Managed.Create();
          foreach(string sPath in sFullPath) {
            // Create a fileStream for the file.
            fileStream = new FileStream(sPath, FileMode.Open);
            // Be sure it's positioned to the beginning of the stream.
            fileStream.Position = 0;
            // Compute the hash of the fileStream.
            hashValue = mySHA256.ComputeHash(fileStream);
            // Close the file.
            fileStream.Close();
            if(string.IsNullOrEmpty(delimiter)) hashStr += byteArrayToString(hashValue);
            else hashStr += string.Format("{0}{1}", byteArrayToString(hashValue), "^");
          }
        }
        if(!string.IsNullOrEmpty(hashStr) && hashStr.Length > 0) {
          hashStr = hashStr.Substring(0, hashStr.Length - 1);
        }
      }
      catch(DirectoryNotFoundException) {
        Console.WriteLine("Error: The directory specified could not be found.");
      }
      catch(IOException) {
        Console.WriteLine("Error: A file in the directory could not be accessed.");
      }
      return hashStr;
    }

    private string byteArrayToString(byte[] bStr) {
      string hexOutput = string.Empty;
      foreach(char letter in bStr) {
        // Get the integral value of the character.
        int value = Convert.ToInt32(letter);
        // Convert the decimal value to a hexadecimal value in string form.
        hexOutput += String.Format("{0:x}", value);
      }
      return hexOutput;
    }
  }
}
