/**
 * Copyright (c) 2003-2004 System Integrator Corporation.
 *                 All Rights Reserved.
 */
package jp.co.sint.beans.front;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.net.UnknownHostException;
import java.sql.Connection;
import java.sql.SQLException;

import javax.naming.NamingException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.swing.JTextArea;

import jp.co.sint.basic.SIFrontBasic;
import jp.co.sint.basic.SILoginSession;
import jp.co.sint.basic.SIUserInfo;
import jp.co.sint.basic.SIPointMan;
import jp.co.sint.basic.SIReserveCartManager;
import jp.co.sint.config.SIConfig;
import jp.co.sint.database.SIDBAccessException;
import jp.co.sint.database.SIDBUtil;
import jp.co.sint.database.SIDatabaseConnection;
import jp.co.sint.database.SIDuplicateKeyException;
import jp.co.sint.database.SIInsertRec;
import jp.co.sint.database.SIModifyRec;
import jp.co.sint.database.SISpcType;
import jp.co.sint.tools.SIBGUtil;
import jp.co.sint.tools.SICheckDataConf;
import jp.co.sint.tools.SICheckUtil;
import jp.co.sint.tools.SICheckValid;
import jp.co.sint.tools.SICustomError;
import jp.co.sint.tools.SICustomErrors;
import jp.co.sint.tools.SIHTMLUtil;
import jp.co.sint.tools.SISessionUtil;
import jp.co.sint.tools.SIURLMap;
import jp.co.sint.tools.SIURLParameter;
import jp.co.sint.tools.SIUtil;

import org.apache.log4j.Category;

/**
 * @version $Id: UIUserLogin.java,v 1.0 2003/10/27 Exp $
 * @author  Jinwang Chen
 * <br>Description:
 * <p>History</p>
 * <p>Author&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Date&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Reason</p>
 *  ============&nbsp;&nbsp;&nbsp;==========&nbsp;&nbsp;===========================<br>
 * Jinwang Chen   2003/10/27 15:36:15  Original
 */
public class UIUserLogin extends SIFrontBasic{
  //ログ用のインスタンスの生成
  private static Category log=Category.getInstance(SIConfig.SILOG4J_WEBSHOP_CATEGORY_NAME);
  
  //顧客名
  private String emailTxt="";
  
  //パスワード
  private String passwordTxt="";
  
  //uid
  private String mobileUid="";
  
  private String nextUrlTxt="";
  
  private String ssouserId="";
  
  public UIUserLogin(){
  }
  
  public void setEmailTxt(String lEmailTxt){
    if (SIUtil.isNull(lEmailTxt)) lEmailTxt="";
    this.emailTxt=SIUtil.changeTo(lEmailTxt.trim(),this.encode);
  }
  
  public void setPasswordTxt(String lPasswordTxt){
    if (SIUtil.isNull(lPasswordTxt)) lPasswordTxt="";
    this.passwordTxt=SIUtil.changeTo(lPasswordTxt.trim(),this.encode);
  }
  
  public void setMobileUid(String lMobileUid){
    if (SIUtil.isNull(lMobileUid)) lMobileUid="";
    this.mobileUid=SIUtil.changeTo(lMobileUid.trim(),this.encode);
  }
  
  public void setNextUrlTxt(String lNextUrlTxt){
    if (SIUtil.isNull(lNextUrlTxt)) lNextUrlTxt="";
    this.nextUrlTxt=SIUtil.changeTo(lNextUrlTxt.trim(),this.encode);
  }
  
  public String getEmailTxt(){
    return this.emailTxt ;
  }
  
  public String getPasswordTxt(){
    return this.passwordTxt;
  }
  
  public String getMibileUid(){
    return this.mobileUid;
  }
  
  public String getNextUrlTxt(){
    return this.nextUrlTxt;
  }
  
  public String getSsouserId(){
    return this.ssouserId;
  }
  
  public void init(HttpServletRequest lRequest,SIURLParameter lUrlParam){
    this.setEncode(SIConfig.SIENCODE_SHIFT_JIS);
    super.init(lRequest,lUrlParam);
    
    if (SIURLMap.isIMode(lRequest)){
      String UA = lRequest.getHeader("user-agent");
      if(SIUtil.isNotNull(UA) && UA.lastIndexOf("ser") < UA.lastIndexOf("icc")){
        this.setMobileUid(UA.substring(UA.lastIndexOf("ser")+3,UA.lastIndexOf("ser")+18));
        log.debug("mobileUID:"+this.mobileUid);
      }else if(SIUtil.isNotNull(UA) && UA.lastIndexOf("ser") > 0){
        this.setMobileUid(UA.substring(UA.lastIndexOf("ser")+3));
        log.debug("mobileUID:"+this.mobileUid);
      }
      if(!SICheckUtil.isDigit(this.mobileUid)) this.setMobileUid("");//数値でない場合は破棄する
    } else if (SIURLMap.isAU(lRequest)) {
      String X_UP_SUBNO = lRequest.getHeader("x-up-subno");
      if (SIUtil.isNotNull(X_UP_SUBNO) && X_UP_SUBNO.length() > 20) {
        this.setMobileUid(X_UP_SUBNO.substring(0, 14));
        log.debug("mobileUID:"+this.mobileUid);
      }
      if(!SICheckUtil.isAlphaDigit(this.mobileUid)) this.setMobileUid("");//英数字でない場合は破棄する
    } else if (SIURLMap.isVod(lRequest)) {
      String UA = lRequest.getHeader("user-agent");
      if (SIUtil.isNotNull(UA) && UA.lastIndexOf("/SN") > 0){
        this.setMobileUid(UA.substring(UA.indexOf("/SN")+3,UA.indexOf(" ")));
        log.debug("mobileUID:"+this.mobileUid);
      }
      if(!SICheckUtil.isDigit(this.mobileUid)) this.setMobileUid("");//数値でない場合は破棄する
    }
    this.setEmailTxt((String)lUrlParam.getParam("emailTxt"));
    this.setPasswordTxt((String)lUrlParam.getParam("passwordTxt"));
    this.setNextUrlTxt((String)lUrlParam.getParam("nid"));
  }
  
  public void initEasyLogin(HttpServletRequest lRequest,SIURLParameter lUrlParam,Connection lConnection){
    this.setEncode(SIConfig.SIENCODE_SHIFT_JIS);
    try {
      this.setEmailTxt(SIDBUtil.getFirstData(lConnection, "SELECT email FROM custtbl WHERE mobileuid = " + SIDBUtil.SQL2Str(getMibileUid())));
      this.setPasswordTxt(SIDBUtil.getFirstData(lConnection, "SELECT password FROM custtbl WHERE mobileuid = " + SIDBUtil.SQL2Str(getMibileUid())));
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
  
  public boolean validate(HttpServletRequest lRequest, HttpServletResponse lResponse, Connection lConnection){
    return validate(lRequest,lResponse,lConnection,false);
  }
  public boolean validate(HttpServletRequest lRequest, HttpServletResponse lResponse, Connection lConnection, boolean easyFlg){
    SICustomErrors errors=new SICustomErrors();
    //StringBuffer lSqlBuf=new StringBuffer();
    //SICust lCust=new SICust();
    SIUserInfo lUserLogin=new SIUserInfo();
    HttpSession session=lRequest.getSession();
    String strNowDateTime = null;
    SIModifyRec siRec = null;
    
    strNowDateTime = SIDBUtil.getDBDateTime(lConnection); //DBから今日の日付を取得
    
    if (easyFlg && SIUtil.isNull(getEmailTxt())) {
      errors.addError(new SICustomError("manager.message.error.nouid"));
    } else {
      SICheckValid.checkValid(errors,"メールアドレス",getEmailTxt(),SICheckDataConf.SICHECK_DATA_EMPTY_TYPE);
      SICheckValid.checkValid(errors,"パスワード",getPasswordTxt(),SICheckDataConf.SICHECK_DATA_EMPTY_TYPE);
    }
    
    if (errors.isEmpty()){
      lUserLogin.setFlg("0");//ログイン処理を行うときのみセッションの最終ログイン日時を更新するため
      lUserLogin.reset(lConnection,getEmailTxt());
      // Web.Xmlの設定値が0以下の場合は機能させない
      if( lUserLogin.getLoginErrDate() != null
          && lUserLogin.getLoginErrDateEdit().equals(strNowDateTime.substring(0,10))
          && Integer.parseInt(lUserLogin.getLoginErrCount()) >= SIConfig.LoginCount
          && SIConfig.LoginCount > 0 ) {
        errors.addError(new SICustomError("app.invalid.login",lUserLogin.getEmail()));// メッセージは通常のログインエラー
      } else {
        if (lUserLogin.getPassword().equals(getPasswordTxt())){
        }else{
          //テーブル名設定
          siRec = new SIModifyRec("CUSTTBL");
          //キー項目設定
          siRec.addCondition("CUSTCODE",lUserLogin.getCustCode());
          //更新内容設定 日付が本日でない場合は１にする、それ以外は＋１
          if( lUserLogin.getLoginErrDateEdit().equals(strNowDateTime.substring(0,10)) ) {
            siRec.add("LOGINERRORCOUNT",new SISpcType(" LOGINERRORCOUNT + 1 "));
          } else {
            siRec.add("LOGINERRORCOUNT",1);
          }
          siRec.add("LOGINERRORDATETIME", strNowDateTime);
          
          //更新実行
          try {
            siRec.execute(lConnection);
            lConnection.commit();
          } catch ( SIDuplicateKeyException siDKExp) {
            siDKExp.printStackTrace();
          } catch ( SIDBAccessException siDAExp) {
            siDAExp.printStackTrace();
          } catch ( SQLException SQLExp) {
            SQLExp.printStackTrace();
          }
          
          errors.addError(new SICustomError("app.invalid.login"));
        }
      }
    }
    
    if (!errors.isEmpty()){//エラーがあれば、ユーザーログイン情報の廃棄
      lRequest.setAttribute(SIConfig.SIERROR_ATTRIBUTE_MESSAGE_KEY,errors);
    }else {//認証OKだったら、ログインユーザ情報をセッションに設定します。
      
      if (!(SIURLMap.isAU(lRequest) && SIConfig.SISSL_FLAG_CURRENT == SIConfig.SISSL_FLAG_ENABLE) && (!SIConfig.SISERVER_TYPE.equalsIgnoreCase("WebSphere"))) {//7.3.0 ST2028 修正
        session = SISessionUtil.sessionRenew(lRequest, lResponse);
      }
      
      session.setAttribute(SIConfig.SISESSION_USERINFO_NAME,lUserLogin);
      lRequest.removeAttribute(SIConfig.SIERROR_ATTRIBUTE_MESSAGE_KEY);
      
      //テーブル名設定
      siRec = new SIModifyRec("CUSTTBL");
      //キー項目設定
      siRec.addCondition("CUSTCODE",lUserLogin.getCustCode());
      //更新内容設定
      siRec.add("LOGINERRORCOUNT",0 );
      siRec.add("LOGINERRORDATETIME", new SISpcType("NULL") );
      
      //更新実行
      try {
        siRec.execute(lConnection);
      } catch ( SIDuplicateKeyException siDKExp) {
        siDKExp.printStackTrace();
      } catch ( SIDBAccessException siDAExp) {
        siDAExp.printStackTrace();
      }
      
      // 携帯以外の場合
      if (!SIURLMap.isMobile(lRequest)) {
        long now = System.currentTimeMillis();
        String sid = SILoginSession.getHash(lUserLogin.getCustCode() + now, "MD5");
        
        //テーブル名設定
        SIInsertRec lRec = new SIInsertRec("LOGINSESSIONTBL");
        lRec.add("sessionid", sid);
        lRec.add("custcode", lUserLogin.getCustCode());
        lRec.add("accessdate", new SISpcType("TO_CHAR(now(),'YYYY/MM/DD HH24:MI:SS')::timestamp"));
        lRec.add("createdate", new SISpcType("TO_CHAR(now(),'YYYY/MM/DD HH24:MI:SS')::timestamp"));
        lRec.add("delflg", 0);
        
        // セッション共有
        Cookie loginCookie = new Cookie(SIConfig.SICOOKIE_LOGIN, sid);
        loginCookie.setDomain("." + SIConfig.BG_HOST_NAME);
        //loginCookie.setDomain("." + "172.30.101.67");
        //loginCookie.setDomain("." + "localhost");
        loginCookie.setPath("/");
        loginCookie.setMaxAge(60 * 60 * 24 * 30);
        lResponse.addCookie(loginCookie);
        
        //レコード登録実行
        try {
          lRec.execute(lConnection);
        } catch ( SIDuplicateKeyException siDKExp) {
          siDKExp.printStackTrace();
        } catch ( SIDBAccessException siDAExp) {
          siDAExp.printStackTrace();
        }
      }
      
    }
    // コミット
    try {
      lConnection.commit();
    } catch ( SQLException SQLExp) {
      SQLExp.printStackTrace();
    }
    
    return errors.isEmpty();
  }
  
  /**
   * 他サイトのユーザーか否か
   * @param lConnection
   * @return boolean
   * @throws UnknownHostException
   * @throws MalformedURLException
   */
  public boolean isPreUser(Connection lConnection) throws MalformedURLException, UnknownHostException{
    try {
      String salt = SIDBUtil.getFirstData(lConnection, "SELECT cov.salt FROM custbasicinfotbl cb INNER JOIN convbtvcusttbl cov ON cb.ssouser_id = cov.ssouser_id WHERE cb.email = " + SIDBUtil.SQL2Str(getEmailTxt()) + " AND cb.custregistflg = 0 AND cov.convert_flag = 0");
      if(salt != ""){
        // TODO 設定ファイルへ
        String requestUrl = "http://www.beautygarage.jp/sso/hash_request.php?pw=" + getPasswordTxt() + "&sl=" + salt;
        String hashPasswd = getHtmlText(new URL(requestUrl));
        int len = hashPasswd.length();
        hashPasswd = hashPasswd.substring(0,len-1);
        //System.out.println("SELECT cov.ssouser_id FROM custbasicinfotbl cb INNER JOIN convbtvcusttbl cov ON cb.ssouser_id = cov.ssouser_id WHERE cb.email = " + SIDBUtil.SQL2Str(getEmailTxt()) + " AND cov.password = " + SIDBUtil.SQL2Str(hashPasswd));
        this.ssouserId = SIDBUtil.getFirstData(lConnection, "SELECT cov.ssouser_id FROM custbasicinfotbl cb INNER JOIN convbtvcusttbl cov ON cb.ssouser_id = cov.ssouser_id WHERE cb.email = " + SIDBUtil.SQL2Str(getEmailTxt()) + " AND cov.password = " + SIDBUtil.SQL2Str(hashPasswd));
        // 平文のパスワードを保持する
        if(this.ssouserId != ""){
          updConvBtvPasswd(lConnection);
          try {
            lConnection.commit();
          } catch (SQLException e) {
            log.debug(e);
            e.printStackTrace();
          }
        }
      }else{
        this.ssouserId = SIDBUtil.getFirstData(lConnection, "SELECT ssouser_id FROM custbasicinfotbl WHERE email = " + SIDBUtil.SQL2Str(getEmailTxt()) + " AND password = " + SIDBUtil.SQL2Str(getPasswordTxt()));
      }
      
    } catch (SIDBAccessException e) {
      log.debug(e);
      e.printStackTrace();
    }
    
    return (this.ssouserId != "");
  }
  
  /**
   * <b>updLoginDateTime</b>
   * 現在日時を最終ログイン日時としてユーザー情報DBを更新する
   * @param  Connection
   * @param  String(メールアドレス)
   * @return void
   * @throws なし
   */
  public void updLoginDateTime(Connection lConnection) {
    SIModifyRec lRec=new SIModifyRec("CustTbl");
    try {
      lRec.addCondition("Email",this.getEmailTxt());//商品コード
      SISpcType lSpcType=new SISpcType();
      lSpcType=new SISpcType("TO_CHAR(now(),'YYYY/MM/DD HH24:MI:SS')::timestamp");
      lRec.add("LoginDateTime",lSpcType);//登録日時
      lRec.execute(lConnection);
    } catch (SIDBAccessException e) {
      log.debug(e);
      e.printStackTrace();
    } catch (SIDuplicateKeyException sqle) {
      log.debug(sqle);
      sqle.printStackTrace();
    }
  }
  
  public void initMobileUid(Connection lConnection) {
    if (SIUtil.isNull(this.getMibileUid())) return;
    SIModifyRec lRec=new SIModifyRec("CustTbl");
    try {
      lRec.addCondition("Email",this.getEmailTxt());
      lRec.add("MobileUid",this.getMibileUid());
      lRec.execute(lConnection);
    } catch (SIDBAccessException e) {
      log.debug(e);
      e.printStackTrace();
    } catch (SIDuplicateKeyException sqle) {
      log.debug(sqle);
      sqle.printStackTrace();
    }
  }
  
  private String getHtmlText(URL url) {
    try{
      JTextArea htmlArea = new JTextArea();
      
      URLConnection uc = url.openConnection();
      BufferedInputStream bis = new BufferedInputStream(uc.getInputStream());
      BufferedReader br = new BufferedReader(new InputStreamReader(bis, "UTF-8"));
      htmlArea.setText("");//初期化
      String line;
      while ((line = br.readLine()) != null) {
          htmlArea.append(line + "\n");
      }
      
      return htmlArea.getText();
      
    } catch(Exception e){
      return "";
    }
  }
  
  public void updConvBtvPasswd(Connection lConnection) {
    SIModifyRec lRec=new SIModifyRec("ConvbtvcustTbl");
    SIModifyRec bRec=new SIModifyRec("CustbasicinfoTbl");
    try {
      lRec.addCondition("ssouser_id",this.ssouserId);//sso_id
      lRec.add("convert_flag",1);// 移行完了
      lRec.execute(lConnection);
      
      bRec.addCondition("ssouser_id",this.ssouserId);//商品コード
      bRec.add("Password",getPasswordTxt());// 移行完了
      bRec.execute(lConnection);
      
    } catch (SIDBAccessException e) {
      log.debug(e);
      e.printStackTrace();
    } catch (SIDuplicateKeyException sqle) {
      log.debug(sqle);
      sqle.printStackTrace();
    }
  }
  
  public static void autoLogin(HttpServletRequest request, HttpServletResponse response) {
    if (SIHTMLUtil.getUserInfo(request).isLogin(request)) return;
    HttpSession session = request.getSession(true);
    UIUserLogin userLogin = new UIUserLogin();
    SIDatabaseConnection databaseConnection = new SIDatabaseConnection();// DBへのコネクションの作成
    
    try{
      Connection lConnection = databaseConnection.getConnection();
      SIBGUtil.readCookie(request,userLogin);
      if (userLogin.validate(request, response, lConnection)) {
        userLogin.updLoginDateTime(lConnection);// DB更新(最終ログイン日時)
        session = request.getSession(true);
        // ポイント期限のチェックと更新
        SIUserInfo lUserLogin = (SIUserInfo) session.getAttribute(SIConfig.SISESSION_USERINFO_NAME);
        SIPointMan.clear(lConnection, lUserLogin.getCustCode());
        SIReserveCartManager.refresh(request, lConnection);
        session.removeAttribute(SIConfig.SISESSION_USER_LOGIN_NAME);
        
        // ポイント再セット
        lUserLogin.reset(lConnection, userLogin.getEmailTxt());
        session.setAttribute(SIConfig.SISESSION_USERINFO_NAME, lUserLogin);
        String value1 = URLEncoder.encode(userLogin.getEmailTxt(), "Shift_JIS");
        String value2 = URLEncoder.encode(userLogin.getPasswordTxt(), "Shift_JIS");
        Cookie mailCookie = new Cookie("ws_mailaddressBG", value1);
        Cookie passCookie = new Cookie("ws_passwordBG", value2);
        mailCookie.setMaxAge(60 * 60 * 24 * 30);
        mailCookie.setDomain("." + SIConfig.BG_HOST_NAME);
        mailCookie.setPath("/");
        passCookie.setMaxAge(60 * 60 * 24 * 30);
        passCookie.setDomain("." + SIConfig.BG_HOST_NAME);
        passCookie.setPath("/");
        response.addCookie(mailCookie);
        response.addCookie(passCookie);
        lConnection.commit();
      }
    }catch(IOException e){
      e.printStackTrace();
    }catch(SQLException e){
      e.printStackTrace();
    }catch(NamingException e){
      e.printStackTrace();
    }finally{
      databaseConnection.close();
    }
  }

}
