<?php

include_once './includes/users/userRights/MemberRight.inc.php';
include_once './includes/users/userRights/MemberRightLister.inc.php';
include_once './includes/users/userRights/MemberRightArray.inc.php';

include_once './includes/exceptions/UserExistsException.inc.php';

include_once './includes/news/ArticleLister.inc.php';

include_once './includes/utils/InputSanitizer.inc.php';
include_once './includes/utils/DateParser.inc.php';

/**
 * This class represents an user in the website system.
 *
 * @author Thomas Schwery
 */
class Member {

    /**
     * The rights of the user
     * @var array(MemberRight)
     */
    private $rights;

    /**
     * The username representing the member.
     * @var string
     */
    private $username;

    /**
     * The password associated with the account
     * @var string
     */
    private $password;

    /**
     * The full name of the member.
     * @var string
     */
    private $fullname;

    /**
     * The date of birth of the member.
     * @var int
     */
    private $birthday;

    /**
     * The email associated with the member.
     * @var string
     */
    private $mail;

    /**
     * An unique identifier for the member.
     * @var int
     */
    private $identifier;

    /**
     * Marker for saving informations into database
     * @var bool
     */
    private $needsSaving;

    /**
     * Returns the user corresponding to the given identifier.
     *
     * @param int $identifier
     * @return Member
     */
    public static function Get($identifier) {
        $sql = "SELECT * FROM users WHERE identifier = $identifier";

        $result = MySQLDatabase::getInstance()->runRequest($sql);

        $newUser = new Member($identifier);

        if ($result) {

            if (array_key_exists(0, $result) && is_array($result[0])) {
                $result = $result[0];
            }

            $newUser->birthday = DateParser::parseSQL($result['birthday']);
            $newUser->fullname = $result['fullName'];
            $newUser->username = $result['username'];
            $newUser->password = $result['password'];
            $newUser->mail = $result['mail'];
            $newUser->rights = MemberRightLister::GetForMember($newUser);
            $newUser->needsSaving = false;

        } else {
            //TODO: Is it necessary ?
            $newUser->birthday = 0;
            $newUser->fullname = "Anonymous User";
            $newUser->password = "-";
            $newUser->username = "anonymous";
            $newUser->mail = "anon@ymo.us";
            $newUser->rights = array();
            $newUser->needsSaving = false;
        }

        return $newUser;
    }

    /**
     * Creates a new user in the database.
     *
     * @param string $fullName
     * @param string $password
     * @param int $birthday
     * @param string $mail
     * @param MemberRight $rights
     *
     * @return int
     *
     * @throws UserExistsException
     */
    public static function Create($fullName, $username, $password, $birthday, $mail, array $rights) {

        $fullName = InputSanitizer::Sanitize($fullName);
        $username = InputSanitizer::Username($username);
        $birthday = InputSanitizer::Number($birthday);
        $mail = InputSanitizer::Sanitize($mail);

        if ($password) {
            $passwordHash = hash("sha512", $password);
        } else {
            $passwordHash = "disabled";
        }

        $user = MemberLister::getByLogin($username);

        if ($user) {
            throw new UserExistsException();
        }

        $birthday = DateFormatter::formatSQL($birthday);

        $sql = "INSERT INTO `users` (
            `identifier`, `fullName`, `username`, `password`, `birthday`, `mail`)
            VALUES (
            NULL, '$fullName', '$username', '$passwordHash', '$birthday', '$mail');";

        $result = MySQLDatabase::getInstance()->runOperation($sql);

        $user = MemberLister::getByLogin($username);
        MemberRightArray::save($rights, $user);

        return $result;
    }

    /**
     * Removes the Member corresponding to the given identifier from the
     * database.
     *
     * @param int $identifier
     * @param boolean $deleteArticles
     * @return int
     */
    public static function Remove($identifier, $deleteArticles) {
        $articles = ArticleLister::getArticleByAuthor(Member::Get($identifier));

        if ($deleteArticles) {
            foreach($articles as $article) {
                Article::Remove($article->getIdentifier());
            }
        } else {
            foreach($articles as $article) {
                $article->setAuthorId(-1);
            }
        }

        $sql = "DELETE FROM `userRightEntries` WHERE `userId` = $identifier";
        $result = MySQLDatabase::getInstance()->runOperation($sql);

        $sql = "DELETE FROM `users` WHERE `identifier` = $identifier";
        $result = MySQLDatabase::getInstance()->runOperation($sql);

        return $result;

    }

    private function  __construct($identifier) {
        $this->identifier = $identifier;
    }

    public function  __destruct() {
        if ($this->needsSaving) {
            $this->save();
        }
    }

    private function save() {

        $birthday = date("Y-m-d H:i:s",$this->birthday);

        $sql = "UPDATE `users` SET
            `birthday` = '$birthday',
            `fullName` = '$this->fullname',
            `password` = '$this->password',
            `mail` = '$this->mail'

            WHERE `identifier` = $this->identifier;";

        $result = MySQLDatabase::getInstance()->runOperation($sql);

        $user = MemberLister::getByLogin($this->username);
        MemberRightArray::save($this->rights, $user);
    }

    public function getIdentifier() {
        return $this->identifier;
    }

    /**
     * @return array(MemberRight)
     */
    public function getRights() {
        return $this->rights;
    }

    public function getUsername() {
        return $this->username;
    }

    public function getFullname() {
        return $this->fullname;
    }

    public function getBirthday() {
        return $this->birthday;
    }

    public function getDate() {
        return $this->getBirthday();
    }

    public function getMail() {
        return $this->mail;
    }

    public function getPassword() {
        return $this->password;
    }

    /**
     * Sets the informations about the user.
     *
     * @param string $fullName
     * @param Right $rights
     * @param string $new_password
     * @param number $birthday
     * @param string $mail
     */
    public function setInformations($fullName, array $rights, $new_password, $birthday, $mail) {

        $fullName = InputSanitizer::Sanitize($fullName);
        $birthday = InputSanitizer::Number($birthday);
        $mail = InputSanitizer::Sanitize($mail);

        $this->birthday = $birthday;
        $this->fullname = $fullName;
        $this->mail = $mail;

        if (strlen($new_password) > 4) {
            $message = "Changing password for user " . $this->username;
            $message .= " from " . $this->password;
            $message .= " to " . $new_password;
            trigger_error($message);
            $passwordHash = hash("sha512", $new_password);
            $this->password = $passwordHash;
        }

        if ($new_password == "-") {
            trigger_error("Disabling password for user " . $this->username);
            $passwordHash = "disabled";
            $this->password = $passwordHash;
        }
        

        $this->rights = $rights;

        $this->needsSaving = true;
    }

    public function checkPassword($password) {
        $passwordHash = hash("sha512", $password);

        return ($this->password == $passwordHash);
    }

}
?>
