package kz.cafe.client.rest;

import java.io.*;
import javax.servlet.http.*;
import javax.ws.rs.*;
import javax.ws.rs.core.*;
import kz.cafe.client.*;
import kz.cafe.client.rest.wrappers.*;
import kz.cafe.constants.*;
import kz.cafe.db.*;
import kz.cafe.db.model.*;
import kz.cafe.db.service.*;
import kz.cafe.exceptions.*;
import kz.cafe.security.*;
import kz.cafe.utils.*;
import org.apache.commons.fileupload.util.*;
import org.apache.commons.logging.*;
import com.google.code.morphia.query.*;


@Path("/user")
public class FEUser extends FEAbstractService{
   //private static Log log = LogFactory.getLog(FEUser.class);

   private static final String LOG = "[JR USER] ";

//   private UserSession4 session = null;





   public FEUser(@Context HttpServletRequest hsr){
      super(ServiceRequestModel.buildUpponServlet(hsr), LOG);
   }

























   @GET
   @Path("/new/{LOGIN}/{PASSWORD}/{LANG}/{NAME}/{PHONE}/{CITY}/{GENDER}/{BIGTHDATE}/{OS}/{DEVICE}")
   @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
   public JRUserCreateResponse newUser(@PathParam("LOGIN")           String sLogin,
                                       @PathParam("PASSWORD")        String sPassword,
                                       @PathParam("LANG")      final String sLang,
                                       @PathParam("NAME")            String sName,
                                       @PathParam("PHONE")           String sPhone,
                                       @PathParam("CITY")            int    iCity,
                                       @PathParam("GENDER")          boolean bGender,
                                       @PathParam("BIGTHDATE")       long lDate,
                                       @PathParam("OS")              String OS,
                                       @PathParam("DEVICE")          String DEVICE){

      JRUserCreateResponse response = new JRUserCreateResponse();
      
      try{
         final MUser mUser = MongoUserService.createEmptyProfile(sLogin);
         
         mUser.login    = sLogin;
         mUser.password = sPassword;
         
         mUser.emailConfirmed = false;
   
         mUser.lang     = validateLang(sLang);          
         

         mUser.name  = sName;
         mUser.phone = sPhone;
         mUser.city  = MongoService.getExceptionable(MCity.class, iCity).ID;

         mUser.gender = bGender;
         
         
         mUser.birthdate = lDate;
         
         
         updateDeviceInfo(mUser, OS, DEVICE);
         uodateLoginTime(mUser);

         
         
         
         MongoUserService.save(mUser);
         
         
         final String sConfirmationCode = "" + new Long(mUser.login.hashCode()) * new Long(mUser.login.hashCode());
         MConfirmationCode mConfirmationCode = new MConfirmationCode();
         mConfirmationCode.code = sConfirmationCode;
         mConfirmationCode.UID = mUser.ID;
         MongoService.ds.save(mConfirmationCode);
         
         
         Thread threadSendConfirmationMail = new Thread(){
            private final Log log = LogFactory.getLog(Thread.class);
            private final String LOG = "[JR USER CONFIRMATION MAIL] ";
            
            public void run() {
               try{
                  InputStream is = ServerConstants.class.getResourceAsStream("/template_email_confirmation_" + sLang.toLowerCase() + ".txt");
                  String sTemplate = Streams.asString(is);
                  sTemplate = sTemplate.replaceAll("%email%", mUser.login);
                  
                  sTemplate = sTemplate.replaceAll("%confirmation_link%", ServerConstants.getEmailConfirmationLink()+ "/" + sConfirmationCode);
                  
                  Mailer.sendMail(ServerConstants.getRobot(),
                                  mUser.login,
                                  "Email Confirmation",
                                  sTemplate);
               }
               catch (IOException e){
                  log.error(LOG, e);
               }
            }
         };
         threadSendConfirmationMail.start();


         long SID = Sessions.open(mUser.ID);
         
         response.SID = super.long2sid(SID);
         response.UID = mUser.ID;
         

         updateStatistic(MAbstractStatistics.F_USER_NEW);
      }
      catch(Throwable e){
         response = new JRUserCreateResponse(e);
      }
      
      super.responseTime(response);
      return response;
   }
   
   

   
   
   @GET
   @Path("/email/confirm/{CODE}")
   @Produces({ MediaType.TEXT_HTML})
   public String confirmEmail(@PathParam("CODE") String sCode){
      MConfirmationCode mConfirmationCode = MongoService.ds.find(MConfirmationCode.class, MConfirmationCode.F_CODE, sCode).get();
      
      if(mConfirmationCode == null){
         return "wrong code";
      }
      else{
         Query<MUser> q =MongoService.ds.createQuery(MUser.class).filter(MUser.F_UID, mConfirmationCode.UID);
         UpdateOperations<MUser> uOps = MongoService.ds.createUpdateOperations(MUser.class).set(MUser.F_EMAIL_CONFIRMED, true);
         MongoService.ds.findAndModify(q, uOps);
         
         
         MongoService.ds.delete(MongoService.ds.createQuery(MConfirmationCode.class).filter(MConfirmationCode.F_CODE, mConfirmationCode.code));
         
         
         return "ok, confirmed.";
      }
   }
   
   
   
   
   
   
   @GET
   @Path("/login/{LOGIN}/{PASSWORD}/{OS}/{DEVICE}")
   @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
   public JRUserLoginResponse login(@PathParam("LOGIN")    String sLogin,
                                    @PathParam("PASSWORD") String sPassword,
                                    @PathParam("OS")       String OS,
                                    @PathParam("DEVICE")   String DEVICE){
      JRUserLoginResponse response = new JRUserLoginResponse();

      try{
         MUser mUser = MongoUserService.getUserProfile(sLogin);
         
         if(mUser.password.equals(sPassword)){
            long SID = Sessions.open(mUser.ID);
            
            response.UID = mUser.ID;
            response.SID = super.long2sid(SID);
            
            updateDeviceInfo(mUser, OS, DEVICE);
            uodateLoginTime(mUser);
            
            MongoUserService.save(mUser);
            updateStatistic(MAbstractStatistics.F_LOGIN_SUCCESS);
         }
         else{
            throw new LoginFailedException(sLogin, sPassword); 
         }
      }
      catch(Throwable e){
         response = new JRUserLoginResponse(e);
      }
      
      updateStatistic(MAbstractStatistics.F_LOGINS);
      super.responseTime(response);
      return response;
   }
   
   

   
   
   @GET
   @Path("/remove/{SID}/{PARAM}")
   @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
   public JRUserCreateResponse updateUserRemoveValue(@PathParam("SID")   String SID,
                                                     @PathParam("PARAM") String sParam){
      return updateUser(SID, sParam, "");
   }
   
   
   
   
   
   
   @GET
   @Path("/update/{SID}/{PARAM}/{VALUE}")
   @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
   public JRUserCreateResponse updateUser(@PathParam("SID")   String SID,
                                          @PathParam("PARAM") String sParam,
                                          @PathParam("VALUE") String sValue){

      JRUserCreateResponse response = new JRUserCreateResponse();
      
      try{
         checkSession(SID);
         
         MUser mUser = MongoUserService.getUserProfile(UID);
         
         
         switch(sParam){
            case "password":{
               mUser.password = sValue;
               
               break;
            }
            case "lang":{
               mUser.lang = validateLang(sValue);          
               
               break;
            }
            case "name":{
               mUser.name = sValue;
               
               break;
            }
            case "phone":{
               mUser.phone = sValue;
               
               break;
            }
            case "city":{
               if("".equals(sValue)) {
                  mUser.city = null;
               }
               else{
                  mUser.city = MongoService.getExceptionable(MCity.class, Integer.parseInt(sValue)).ID;
               }
               
               break;
            }
            case "avatar":{
               if("".equals(sValue)){
                  mUser.image = null;
               }
               else{
                  mUser.image = sValue;
               }
               
               break;
            }
            case "gender":{
               mUser.gender = Boolean.parseBoolean(sValue);
               
               break;
            }
            
            case "birthday":{
               mUser.birthdate = Long.parseLong(sValue);
               
               break;
            }
         }
         
         MongoUserService.save(mUser);
      }
      catch(Throwable e){
         response = new JRUserCreateResponse(e);
      }
      
      super.responseTime(response);
      return response;
   }
   

   
   
   
   
   
   @GET
   @Path("/profile/{SID}")
   @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
   public JRUserProfileResponse getProfile(@PathParam("SID") String SID){

      JRUserProfileResponse response = new JRUserProfileResponse();
      
      try{
         checkSession(SID);
         
         MUser mUser = MongoUserService.getUserProfile(super.UID);
         
         response.birthdate = mUser.birthdate;
         response.dateLatestLogin = mUser.dateLatestLogin;
         response.dateRegistration = mUser.dateRegistration;
         response.gender = mUser.gender;
         response.lang   = mUser.lang.name();
         response.name   = mUser.name;
         response.phone  = mUser.phone;
         response.city   = mUser.city;
         response.avatar = mUser.image;
         
      }
      catch(Throwable e){
         response = new JRUserProfileResponse(e);
      }
      
      super.responseTime(response);
      return response;
   }
   

   
   
   
   
   @GET
   @Path("/password/recovery/{lang}/{email}")
   @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
   public JREmptyResponse password(@PathParam("lang") String sLang,
                                   @PathParam("email") String sEmail){

      JREmptyResponse response = new JREmptyResponse();
      
      try{
         checkLanguage(sLang);
         
         MUser mUser = MongoUserService.getUserProfile(sEmail);
         
         InputStream is = ServerConstants.class.getResourceAsStream("/template_password_recovery_" + sLang.toLowerCase() + ".txt");
         String sTemplate = Streams.asString(is);
         sTemplate = sTemplate.replaceAll("%login%", mUser.login);
         sTemplate = sTemplate.replaceAll("%password%", mUser.password);
         
         Mailer.sendMail(ServerConstants.getRobot(),
                         sEmail,
                         "password",
                         sTemplate);
      }
      catch(Throwable e){
         response = new JREmptyResponse(e);
      }
      
      super.responseTime(response);
      return response;
   }
   
   
   
   
   
   

   
   

   
   
   
   private static void updateDeviceInfo(MUser mUser, String OS, String DEVICE){
      MUser.Device device = new MUser.Device(DEVICE, OS); 
      
      mUser.device = device;
      
      if(mUser.devices.contains(device)){
      }
      else{
         mUser.devices.add(device);
      }
   }

   
   

   

   private static void uodateLoginTime(MUser mUser){
      mUser.dateLatestLogin = System.currentTimeMillis();
   }
}

