<?php

class SessionController extends Controller
{
  public function filters()
  {
    return array(
        array('application.filters.SyslogFilter',),
    );
  }

  public function actionRefreshPassword($username)
  {
    $model = new RefreshPasswordForm();
    $model->username = $username;

    $modelfocus = 'old_password';

    if(isset($_POST['RefreshPasswordForm']))
    {
      $info = $_POST['RefreshPasswordForm'];

      $model->username = $info['username'];

      $auth = new UserIdentity($info['username'], $info['old_password']);

      if($auth->authenticate())
      {
        $model->old_password = $info['old_password'];
        $usrs=User::model()->findAllBySql("select * from users where username=:username", array(':username'=>$username));
        $usr=$usrs[0];

        if($info['new_password'] != '')
        {
          if($info['new_password'] != $info['old_password'])
          {
            $model->new_password = $info['new_password'];

            if($info['repeat_new_password'] == $info['new_password'])
            {
              $usr->password = $usr->hashPassword($model->new_password);
              $usr->password_last_update = date("Y-m-d H:i:s");
              $usr->refresh_password_at_first_login = 0;

              if($usr->update(array('password','password_last_update','refresh_password_at_first_login')))
              {
                security_log("PASSWORD REFRESH FOR USER '$info[username]'", "login",false);
                $this->redirect(Yii::app()->user->returnUrl);
                return;
              }
            }
            else
            {
              $model->addError('repeat_new_password', Yii::t('app', 'New passwords must coincide'));
              $modelfocus = 'repeat_new_password';
            }
          }
          else
          {
            $model->addError('new_password', Yii::t('app', 'New password must be different than the old one'));
            $modelfocus = 'new_password';
          }
        }
        else
        {
          $model->addError('new_password', Yii::t('app', 'New password cannot be empty'));
          $modelfocus = 'new_password';
        }
      }
      else
      {
        $model->addError('old_password', Yii::t('app', 'Username and old password do not match'));
        $modelfocus = 'old_password';
      }
    }

    $this->render('refreshpassword',array('model'=>$model, 'modelfocus'=>$modelfocus));
  }

  public function actionLogin()
  {
    $model = new LoginForm;

    if(!isEmpty($_REQUEST['impersonate']))
    {
      if(!$this->impersonate($_REQUEST['impersonate']))
        $this->render('login',array('model'=>$model));
      return;
    }

    if(isset($_POST['LoginForm']))
    {
      $loginInfo = $_POST['LoginForm'];
      $model->attributes = $loginInfo;
      if($model->validate() && $model->login())
      {
        $user = Yii::app()->user->model;
        $usercanchangepwd = ($user->can_change_password == null || $user->can_change_password == 1);

        if($usercanchangepwd && $user->refresh_password_at_first_login != null && $user->refresh_password_at_first_login)
        {
          $pwdmustchange = true;
          if($pwdmustchange)
          {
            security_log("PASSWORD MUST BE CHANGED FOR USER '$model->username'", "login",false);
            Yii::app()->user->logout();
            $this->redirect(array('session/refreshpassword', 'username'=>$model->username));
            return;
          }
        }
        // prima di creare la sessione, devo cambiare la password....
        else if($user->password_timeout != null && $user->password_timeout > 0)
        {
          $now = new DateTime(); // date("Y-m-d H:i:s");

          $remainingDays = -1;
          $pwdmustchange = false;

          if($user->password_last_update == null)
            $pwdmustchange = true;
          else
          {
            $lastpwdchange = new DateTime($user->password_last_update);
            $interval = $now->diff($lastpwdchange);
            if( $interval->days >= 0 )
            {
              if( $interval->days > $user->password_timeout )
              {
                $pwdmustchange = true;
              }
              else
              {
                $remainingDays = $user->password_timeout - $interval->days;
              }
            }
            else
            {
            }
          }


          if($pwdmustchange)
          {
            Yii::app()->user->logout();
            if($usercanchangepwd)
            {
              security_log("PASSWORD MUST BE CHANGED FOR USER '$model->username'", "login",false);
              // porto a pagina cambio password
              $this->redirect(array('session/refreshpassword', 'username'=>$model->username));
              return;
            }
            else
            {
              security_log("PASSWORD MUST BE CHANGED BY ADMIN FOR USER '$model->username'", "login",false);
              // mostro messaggio e return!
              Yii::app()->user->setFlash('notice', Yii::t('app', 'Your password is expired and must be changed, please contact an administrator'));
              $this->render('login',array('model'=>$model));
              return;
            }
          }
          else
          {
            if($remainingDays >= 0 && $remainingDays <= Yii::app()->params['passwordExpirationNotification'])
            {
              if($usercanchangepwd)
                Yii::app()->user->setFlash('notice', Yii::t('app', 'Your password will expire in {remainingDays} days', array('{remainingDays}'=>$remainingDays)));
              else
                Yii::app()->user->setFlash('notice', Yii::t('app', 'Your password will expire in {remainingDays} days, please contact an administrator', array('{remainingDays}'=>$remainingDays)));
            }
          }
        }

        security_log("LOGIN USER '$model->username'", "login",false);
        // sessioni etc...
        $sessionId = Yii::app()->session->sessionId;
        $this->deleteAllSessions($user, array($sessionId));
        $this->linkSessionToUser($user);
        $this->startWorkPeriod($user);
        // debug
        //logObjs('autoEnable',paramdeep('debug','autoEnable'));
        //logObjs('checkAccess',user()->checkAccess('debug'));
        if(paramdeep('debug','autoEnable') && user()->checkAccess('debug'))
          DebugController::enableDebugMode();
        else
          DebugController::disableDebugMode();
        // fix redir x evitare doppio login
        $redirUrl = Yii::app()->user->returnUrl;
        if(empty($redirUrl) || endsWith($redirUrl, "logout"))
          $redirUrl = url('/');
        $this->redirect($redirUrl);
        return;
      }
      else security_log("LOGIN USER '$model->username' FAILED BY $_SERVER[REMOTE_ADDR] with password ".CaesarCipher::enc($model->password), "login",false);
    }

    $this->render('login',array('model'=>$model));
  }

  protected function impersonate($token)
  {
    $user = User::findByImpersonationToken($token);
    if($user == null)
    {
      security_log("IMPERSONATION BY TOKEN '$token' FAILED, USER NOT FOUND!", "login", false);
      user()->setFlash('error', 'Impersonation failed!');
      return false;
    }
    security_log("IMPERSONATION OF USER '$user->username' BY TOKEN '$token', SUCCESS!", "login", false);
    // sessioni etc...
    user()->impersonate($user->id, $user->username);
    $sessionId = Yii::app()->session->sessionId;
    $this->deleteAllSessions($user, array($sessionId));
    $this->linkSessionToUser($user);
    $this->startWorkPeriod($user);
    // debug
    if(paramdeep('debug','autoEnable') && user()->checkAccess('debug'))
      DebugController::enableDebugMode();
    else
      DebugController::disableDebugMode();
    // redir
    $redirUrl = user()->returnUrl;
    if(empty($redirUrl) || endsWith($redirUrl, "logout"))
      $redirUrl = url('/');
    $this->redirect($redirUrl);
  }

  public function actionLogout()
  {
    $username = app()->user->model->username;
    security_log("LOGOUT USER '$username'", "login",false);

    $user = Yii::app()->user->model;
    $wpid = $this->stopWorkPeriod($user);

    user()->logout();

    $this->redirect(url('session/login'));
    //$this->redirect(Yii::app()->homeUrl);//ri-disabilitato, a volte porta alla dashboard ma senza login fallisce quando non trova workperiod valido
  }

  private function deleteAllSessions($user, $exceptIds = array())
  {
    $sessions = Session::model()->byUser($user)->findAll();
    foreach($sessions as $session)
    {
      if (!in_array($session->id, $exceptIds))
        $session->delete();
    }
  }

  private function linkSessionToUser($user)
  {
    $session = Session::model()->findByPk(Yii::app()->session->sessionId);
    if ($session == null || !$session->linkToUser($user))
      throw new CException(Yii::t('app', 'Cannot assign user to current session.'));

    return true;
  }

  private function startWorkPeriod($user)
  {
    $period = new WorkPeriod;
    if (!$period->start($user))
      throw new CException(Yii::t('app', 'Cannot initialize a new work period.'));

    return true;
  }

  private function stopWorkPeriod($user)
  {
    if($user == null)
      return -1;
    $workPeriod = WorkPeriod::model()->byUser($user)->open()->find();
    if($workPeriod != null)
    if (!$workPeriod->stop())
      throw new CException(Yii::t('app', 'Cannot close an open work period.'));
    else
      return $workPeriod->id;
    else
      return -1;
  }

}
