<?php
/*********************************************************************
    class.client.php

    Handles everything about EndUser

    Peter Rotich <peter@osticket.com>
    Copyright (c)  2006-2013 osTicket
    http://www.osticket.com

    Released under the GNU General Public License WITHOUT ANY WARRANTY.
    See LICENSE.TXT for details.

    vim: expandtab sw=4 ts=4 sts=4:
**********************************************************************/
abstract class TicketUser {

    static private $token_regex = '/^(?P<type>\w{1})(?P<id>\d+)t(?P<tid>\d+)x(?P<algo>\d+)h(?P<hash>.*)$/i';

    protected  $user;

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

    function __call($name, $args) {
        global $cfg;

        if($this->user && is_callable(array($this->user, $name)))
            return  $args
                ? call_user_func_array(array($this->user, $name), $args)
                : call_user_func(array($this->user, $name));

        $tag =  substr($name, 3);
        switch (strtolower($tag)) {
            case 'ticket_link':
                return sprintf('%s/view.php?auth=%s',
                        $cfg->getBaseUrl(),
                        urlencode($this->getAuthToken()));
                break;
        }

        return false;

    }

    protected function getAuthToken($type=1) {

        //Format: // c<id>x<algo id used>h<hash for algo>
        $authtoken = '';
        switch($type) {
            case 1:
                $authtoken = sprintf('%s%dt%dx%dh%s',
                        ($this->isOwner() ? 'o' : 'c'),
                        $this->getId(),
                        $this->getTicketId(),
                        $type,
                        substr(base64_encode(md5($this->getId().$this->getTicket()->getCreateDate().$this->getTicketId().SECRET_SALT,
                                    true)), 16));
                break;
        }

        //TODO: Throw an exception
        if (!$authtoken)
            return false;

        return $authtoken;
    }

    static function lookupByToken($token) {

        //Expecting well formatted token see getAuthToken routine for details.
        $matches = array();
        if (!preg_match(static::$token_regex, $token, $matches))
            return null;

        $user = null;
        switch ($matches['type']) {
            case 'c': //Collaborator c
                if (($user = Collaborator::lookup($matches['id']))
                        && $user->getTicketId() != $matches['tid'])
                    $user = null;
                break;
            case 'o': //Ticket owner
                if (($ticket = Ticket::lookup($matches['tid']))) {
                    if (($user = $ticket->getOwner())
                            && $user->getId() != $matches['id'])
                        $user = null;
                }
                break;
        }

        if (!$user
                || !$user instanceof TicketUser
                || strcasecmp($user->getAuthToken($matches['algo']), $token))
            return false;

        var_dump($user);

        return $user;
    }

    function isOwner() {
        return  ($this->user
                    && $this->user->getId() == $this->getTicket()->getOwnerId());
    }

    abstract function getTicketId();
    abstract function getTicket();
}

class TicketOwner extends  TicketUser {

    protected $ticket;

    function __construct($user, $ticket) {
        parent::__construct($user);
        $this->ticket = $ticket;
    }

    function getTicket() {
        return $this->ticket;
    }

    function getTicketId() {
        return $this->ticket->getId();
    }
}

/*
 * Decorator class for authenticated user
 *
 */

class  EndUser extends AuthenticatedUser {

    protected $user;

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

    /*
     * Delegate calls to the user
     */
    function __call($name, $args) {

        if(!$this->user
                || !is_callable(array($this->user, $name)))
            return false;

        return  $args
            ? call_user_func_array(array($this->user, $name), $args)
            : call_user_func(array($this->user, $name));
    }

    function getId() {
        //We ONLY care about user ID at the ticket level
        if ($this->user instanceof Collaborator)
            return $this->user->getUserId();

        return $this->user->getId();
    }

    function getUserName() {
        //XXX: Revisit when real usernames are introduced  or when email
        // requirement is removed.
        return $this->user->getEmail();
    }

    function getRole() {
        return $this->isOwner() ? 'owner' : 'collaborator';
    }

    function logOut() {
        return UserAuthenticationBackend::signOut($this);
    }

    function getTicketStats() {

        if (!isset($this->ht['stats']))
            $this->ht['stats'] = $this->getStats();

        return $this->ht['stats'];
    }

    function getNumTickets() {
        return ($stats=$this->getTicketStats())?($stats['open']+$stats['closed']):0;
    }

    function getNumOpenTickets() {
        return ($stats=$this->getTicketStats())?$stats['open']:0;
    }

    function getNumClosedTickets() {
        return ($stats=$this->getTicketStats())?$stats['closed']:0;
    }

    private function getStats() {

        $sql='SELECT count(open.ticket_id) as open, count(closed.ticket_id) as closed '
            .' FROM '.TICKET_TABLE.' ticket '
            .' LEFT JOIN '.TICKET_TABLE.' open
                ON (open.ticket_id=ticket.ticket_id AND open.status=\'open\') '
            .' LEFT JOIN '.TICKET_TABLE.' closed
                ON (closed.ticket_id=ticket.ticket_id AND closed.status=\'closed\')'
            .' LEFT JOIN '.TICKET_COLLABORATOR_TABLE.' collab
                ON (collab.ticket_id=ticket.ticket_id
                    AND collab.user_id = '.db_input($this->getId()).' )'
            .' WHERE ticket.user_id = '.db_input($this->getId())
            .' OR collab.user_id = '.db_input($this->getId());

        return db_fetch_array(db_query($sql));
    }


}
?>