<?php

class AccountController extends Zend_Controller_Action {
  public function isAcceptNewAccount() {
    $max = Zend_Controller_Front::getInstance()
      ->getParam('config')
      ->account
      ->registration
      ->max;

    $acct_t = new Account();
    $num_acct = $acct_t->fetchAll(
      $acct_t->select()->from($acct_t, 'COUNT(*) AS count')
    )->current()->count;

    return ((int)$num_acct < (int)$max);
  }

  ////////////////////////////////////////////////////////////////////////////
  //
  // SessionMessage
  //
  ////////////////////////////////////////////////////////////////////////////
  public function setSessionMessage($msg) {
    $s = new Zend_Session_Namespace('sessionMessage');
    $s->setExpirationHops(1);
    $s->msg = $msg;
  }

  public function getSessionMessage() {
    $s = new Zend_Session_Namespace('sessionMessage');
    return $s->msg;
  }

  ////////////////////////////////////////////////////////////////////////////
  //
  // Form
  //
  ////////////////////////////////////////////////////////////////////////////
  private function getRegistrationForm() {
    $form = new Zend_Form;

    $form->setAction('/account/registration-submit')->setMethod('post');

    $rule = $form->createElement(
      'checkbox',
      'rule',
      array('label' => 'ねこすけLPO利用規約に同意します')
    );
    $rule->setRequired(true);

    $name = $form->createElement(
      'text',
      'name',
      array('label' => 'お名前')
    );
    $name->setRequired(true);

    $email = $form->createElement(
      'text',
      'email',
      array('label' => 'メールアドレス')
    );
    $email->setRequired(true);
    $email->addValidator('EmailAddress');

    $password = $form->createElement(
      'password',
      'password',
      array('label' => 'パスワード')
    );
    $password->setRequired(true);

    $submit = $form->createElement(
      'submit',
      'submit',
      array('label' => '登録')
    );

    $form->addElement($rule);
    $form->addElement($name);
    $form->addElement($email);
    $form->addElement($password);
    $form->addElement($submit);

    return $form;
  }

  public function getLoginForm() {
    $form = new Zend_Form;

    $form->setAction('/account/login-submit')->setMethod('post');

    $email = $form->createElement(
      'text',
      'email',
      array('label' => 'メールアドレス')
    );
    $email->addValidator('stringLength', false, array(1, 255));
    $email->setRequired(true);

    $password = $form->createElement(
      'password',
      'password',
      array('label' => 'パスワード')
    );
    $password->addValidator('stringLength', false, array(1, 255));
    $password->setRequired(true);

    $session = $form->createElement(
      'checkbox',
      'session',
      array('label' => '次回から入力を省略')
    );

    $submit = $form->createElement(
      'submit',
      'submit',
      array('label' => 'ログイン')
    );

    $form->addElement($email);
    $form->addElement($password);
    $form->addElement($session);
    $form->addElement($submit);

    return $form;
  }

  public function getEmailForm() {
    $form = new Zend_Form;

    $form->setAction('/account/reminder-submit')->setMethod('post');

    $email = $form->createElement(
      'text',
      'email',
      array('label' => 'メールアドレス')
    );
    $email->setRequired(true);
    $email->addValidator('EmailAddress');

    $submit = $form->createElement(
      'submit',
      'submit',
      array('label' => '送信')
    );

    $form->addElement($email);
    $form->addElement($submit);

    return $form;
  }

  public function getPasswordForm() {
    $form = new Zend_Form;

    $form->setAction(
      '/account/reset-password-submit/key/' .
      $this->getRequest()->getParam('key')
    )->setMethod('post');

    $password = $form->createElement(
      'password',
      'password',
      array('label' => '新しいパスワード')
    );
    $password->setRequired(true);

    $submit = $form->createElement(
      'submit',
      'submit',
      array('label' => '設定')
    );

    $form->addElement($password);
    $form->addElement($submit);

    return $form;
  }

  ////////////////////////////////////////////////////////////////////////////
  //
  // Dispatch
  //
  ////////////////////////////////////////////////////////////////////////////
  public function preDispatch() {
    if($this->getRequest()->getActionName() == 'logout') {
      return;
    }

    if(Zend_Auth::getInstance()->hasIdentity()) {
      return $this->_redirect('/');
    }
  }

  ////////////////////////////////////////////////////////////////////////////
  //
  // Action
  //
  ////////////////////////////////////////////////////////////////////////////
  public function menuAction() {
    $this->view->action = $this->getRequest()->getParam('action');
    $this->render(null, 'menu');
  }

  public function msgAction() {
    $this->view->msg = $this->getSessionMessage();
    $this->render(null, 'msg');
  }

  public function indexAction() {
    $this->_helper->actionStack('msg');
    $this->_helper->actionStack('menu');
  }

  public function registrationAction() {
    $this->_helper->actionStack('msg');
    $this->_helper->actionStack('menu');

    if($this->isAcceptNewAccount()) {
      $this->view->form = $this->getRegistrationForm();
    } else {
      $this->view->form = null;
    }
  }

  public function registrationSubmitAction() {
    $this->_helper->actionStack('msg');
    $this->_helper->actionStack('menu');

    if(!$this->isAcceptNewAccount()) {
      return $this->_forward('registration');
    }

    if(!$this->getRequest()->isPost()) {
      return $this->_forward('registration');
    }

    $form = $this->getRegistrationForm();

    if(!$form->isValid($_POST)) {
      $this->view->form = $form;
      return $this->render('registration');
    }

    $reg_t = new Registration;
    $reg = $reg_t->createRow();
    $reg->name     = $form->getElement('name')->getValue();
    $reg->email    = $form->getElement('email')->getValue();
    $reg->password = $form->getElement('password')->getValue();
    $reg->save();

    $config = Zend_Controller_Front::getInstance()->getParam('config');

    $this->view->reg = $reg;
    $this->view->base_url = $config->base_url;

    $mail_config = $config->mail->registration->submit;

    $mail = new Necosuke_Mail;
    $mail->setBodyText($this->view->render($mail_config->template));
    $mail->setFrom($mail_config->from_email, $mail_config->from_name);
    $mail->addTo($reg->email, $reg->name);
    $mail->setSubject($mail_config->subject);
    $mail->send();
  }

  public function confirmAction() {
    $this->_helper->actionStack('msg');
    $this->_helper->actionStack('menu');

    $hash = $this->getRequest()->getParam('key');

    if(!$hash) {
      return $this->_redirect('/account/confirm-error');
    }

    $reg_t = new Registration;
    $reg = $reg_t->fetchRow($reg_t->select()->where('hash = ?', $hash));

    if(!$reg) {
      return $this->_redirect('/account/confirm-error');
    }

    $acct_t = new Account;

    $a = $acct_t->fetchRow(
      $acct_t->select()
        ->where('email = ?', $reg->email)
        ->where('status = ?', 'active')
    );
    if($a) {
      $reg->delete();
      return $this->_redirect('/account/confirm-error-already-exists');
    }

    $acct  = $acct_t->createRow();
    $acct->name     = $reg->name;
    $acct->email    = $reg->email;
    $acct->password = $reg->password;
    $acct->save();

    $reg->delete();

    $config = Zend_Controller_Front::getInstance()->getParam('config');

    $this->view->acct = $acct;
    $this->view->base_url = $config->base_url;

    $mail_config = $config->mail->registration->confirm;

    $mail = new Necosuke_Mail;
    $mail->setBodyText($this->view->render($mail_config->template));
    $mail->setFrom($mail_config->from_email, $mail_config->from_name);
    $mail->addTo($acct->email, $acct->name);
    $mail->setSubject($mail_config->subject);
    $mail->send();
  }

  public function confirmErrorAction() {
  }

  public function confirmErrorAlreadyExistsAction() {
  }

  public function loginAction() {
    $this->_helper->actionStack('msg');
    $this->_helper->actionStack('menu');

    $this->view->form = $this->getLoginForm();
  }

  public function loginSubmitAction() {
    $this->_helper->actionStack('msg');
    $this->_helper->actionStack('menu');

    if(!$this->getRequest()->isPost()) {
      return $this->_forward('login');
    }

    $form = $this->getLoginForm();

    if(!$form->isValid($_POST)) {
      $this->view->form = $form;
      return $this->render('login');
    }

    $acct_t = new Account();

    $adapter = new Zend_Auth_Adapter_DbTable(
      Zend_Db_Table_Abstract::getDefaultAdapter(),
      $acct_t->info('name'),
      'email',
      'password',
      'SHA1(?) AND status = "active"'
    );
    $adapter->setIdentity($form->getElement('email')->getValue());
    $adapter->setCredential($form->getElement('password')->getValue());

    $ret = Zend_Auth::getInstance()->authenticate($adapter);

    if(!$ret->isValid()) {
      $this->setSessionMessage('ユーザ名またはパスワードが違います');
      $this->view->form  = $form;
      return $this->_redirect('/account/login');
    }

    $acct = $acct_t->fetchRow(
      $acct_t->select()->where(
        "email = ? AND status = 'active'",
        $form->getElement('email')->getValue()
      )
    );
    $acct->logined = date('Y-m-d H:i:s');
    $acct->save();

    if($form->getElement('session')->getValue()) {
      Zend_Session::rememberMe(
        Zend_Controller_Front::getInstance()
          ->getParam('config')
          ->login
          ->rememberme
      );
    }

    return $this->_redirect('/');
  }

  public function logoutAction() {
    $this->_helper->actionStack('msg');
    $this->_helper->actionStack('menu');

    Zend_Auth::getInstance()->clearIdentity();
  }

  public function reminderAction() {
    $this->_helper->actionStack('msg');
    $this->_helper->actionStack('menu');

    $this->view->form = $this->getEmailForm();
  }

  public function reminderSubmitAction() {
    $this->_helper->actionStack('msg');
    $this->_helper->actionStack('menu');

    if(!$this->getRequest()->isPost()) {
      return $this->_redirect('/account/reminder');
    }

    $form = $this->getEmailForm();

    if(!$form->isValid($_POST)) {
      $this->view->form = $form;
      return $this->render('reminder');
    }

    $acct_t = new Account;
    $acct   = $acct_t->fetchRow(
      $acct_t->select()->where(
        "email = ? AND status = 'active'",
        $form->getElement('email')->getValue()
      )
    );

    if(!$acct) {
      return $this->_redirect('/account/reminder-error-account-not-exists');
    }

    $rmdr_t = new Reminder;
    $rmdr   = $rmdr_t->createRow();
    $rmdr->email = $acct->email;
    $rmdr->save();

    $this->view->user = $acct;
    $this->view->key  = $rmdr->hash;

    $config = Zend_Controller_Front::getInstance()->getParam('config');

    $this->view->base_url = $config->base_url;
    $mail_config = $config->mail->account->reminder;

    $mail = new Necosuke_Mail;
    $mail->setBodyText($this->view->render($mail_config->template));
    $mail->setFrom($mail_config->from_email, $mail_config->from_name);
    $mail->addTo($acct->email, $acct->name);
    $mail->setSubject($mail_config->subject);
    $mail->send();
  }

  public function reminderErrorAccountNotExistsAction() {
    $this->_helper->actionStack('msg');
    $this->_helper->actionStack('menu');
  }

  public function resetPasswordAction() {
    $this->_helper->actionStack('msg');
    $this->_helper->actionStack('menu');

    $rmdr_t = new Reminder;
    $rmdr   = $rmdr_t->fetchRow(
      $rmdr_t->select()->where(
        'hash = ?',
        $this->getRequest()->getParam('key')
      )
    );

    if(!$rmdr) {
      return $this->_redirect('/account/reset-password-error-invalid-key');
    }

    $this->view->form = $this->getPasswordForm();
  }

  public function resetPasswordSubmitAction() {
    $this->_helper->actionStack('msg');
    $this->_helper->actionStack('menu');

    if(!$this->getRequest()->isPost()) {
      return $this->_redirect('/account/reset-password');
    }

    $form = $this->getPasswordForm();

    if(!$form->isValid($_POST)) {
      $this->view->form = $form;
      return $this->render('reset-password');
    }

    $rmdr_t = new Reminder;
    $rmdr   = $rmdr_t->fetchRow(
      $rmdr_t->select()->where(
        'hash = ?',
        $this->getRequest()->getParam('key')
      )
    );

    if(!$rmdr) {
      return $this->_redirect('/account/reset-password-error-invalid-key');
    }

    $acct_t = new Account;
    $acct   = $acct_t->fetchRow(
      $acct_t->select()->where("email = ? AND status = 'active'", $rmdr->email)
    );

    if(!$acct) {
      return $this->_redirect(
        '/account/reset-password-error-account-not-exists'
      );
    }

    $acct->password = $this->getRequest()->getParam('password');
    $acct->save();

    $rmdr->delete();
  }

  public function resetPasswordErrorInvalidKeyAction() {
    $this->_helper->actionStack('msg');
    $this->_helper->actionStack('menu');
  }

  public function resetPasswordErrorAccountNotExistsAction() {
    $this->_helper->actionStack('msg');
    $this->_helper->actionStack('menu');
  }

  public function aboutAction() {
    $this->_helper->actionStack('msg');
    $this->_helper->actionStack('menu');
  }
}
