<?php
/**
 * Controller for photo
 *
 * This file is part of Zoph.
 *
 * Zoph is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * Zoph is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * You should have received a copy of the GNU General Public License
 * along with Zoph; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * @package Zoph
 * @author Jeroen Roos
 */

namespace photo;

use conf\conf;
use generic\controller as genericController;
use web\request;

use album;
use breadcrumb;
use log;
use photo;
use rating;
use user;

use photoNotAccessibleSecurityException;


/**
 * Controller for photo
 */
class controller extends genericController {

    /** @var array Actions that can be used in this controller */
    protected   $actions    = array(
        "confirm", "delete", "delrate", "deselect", "display", "edit",
        "lightbox", "rate", "select", "update", "unlightbox"
    );

    /** @var string Where to redirect after actions */
    public $redirect="photo.php";

    /** @var int total number of photos return by the query */
    public $photocount = 0;
    /** @var int offset in the query for the current photo */
    public $offset = 0;

    /**
     * Create a controller using a web request
     * @param request request
     */
    public function __construct(request $request) {
        parent::__construct($request);

        try {
            $photo=$this->getPhotoFromRequest();
        } catch (photoNotAccessibleSecurityException $e) {
            log::msg($e->getMessage(), log::WARN, log::SECURITY);
            $photo=null;
        }

        if ($photo instanceof photo) {
            $this->setObject($photo);
            $this->doAction();
        } else {
            $this->view = "notfound";
        }
    }

    /**
     * Get the photo based on the query in the request
     * @throws photoNotAccessibleSecurityException
     */
    private function getPhotoFromRequest() {
        $user=user::getCurrent();
        if (isset($this->request["photo_id"])) {
            $photo = new photo($this->request["photo_id"]);
            $photo->lookup();
        } else {
            $offset = isset($this->request["_off"]) ? $this->request["_off"] : 0;
            $photoCollection = collection::createFromRequest(request::create());

            $this->photocount=sizeof($photoCollection);
            $this->offset=$offset;

            $photos=$photoCollection->subset($offset, 1);
            if ($photos) {
                $photo = $photos->shift();
            } else {
                $photo = new photo();
            }
        }
        if ($user->isAdmin() || $user->getPhotoPermissions($photo)) {
            return $photo;
        }
        throw new photoNotAccessibleSecurityException(
            "Security Exception: photo " . $photo->getId() .
            " is not accessible for user " . $user->getName() . " (" . $user->getId() . ")"
        );
    }

    /**
     * Do action 'confirm'
     */
    public function actionConfirm() {
        if (user::getCurrent()->canDeletePhotos()) {
            parent::actionConfirm();
        } else {
            $this->view="display";
        }
    }

    /**
     * Do action 'delete'
     */
    public function actionDelete() {
        if (user::getCurrent()->canDeletePhotos()) {
            parent::actionDelete();
        } else {
            $this->view="display";
        }
    }


    /**
     * Do action 'delrate'
     */
    public function actionDelrate() {
        if (user::getCurrent()->isAdmin()) {
            $ratingId=$this->request["_rating_id"];
            $rating=new rating((int) $ratingId);
            $rating->delete();
            breadcrumb::init();
            $this->redirect = html_entity_decode(breadcrumb::getLast()->getURL());
            if (!$this->redirect) {
                $this->redirect = "zoph.php";
            }
            $this->view="redirect";
        }
    }

    /**
     * Do action 'deselect'
     * @todo the $_SESSION access should be refactored into a separate session class
     */
    public function actionDeselect() {
        $selectKey=array_search($this->request["photo_id"], $_SESSION["selected_photo"]);

        if ($selectKey !== false) {
            unset($_SESSION["selected_photo"][$selectKey]);
        }
        $this->redirect=$this->request["_return"] . "?" . $this->request->getPassedQueryString();

        $this->view="redirect";
    }

    /**
     * Do action 'display'
     */
    public function actionDisplay() {
        $user = user::getCurrent();
        if (
            $user->prefs->get("auto_edit")  &&
            (!isset($this->request["_action"]) || $this->request["_action"] == "search") &&
            $this->object->isWritableBy($user)) {

            $this->view="update";
        } else {
            $this->view="display";
        }
    }

    /**
     * Do action 'display'
     */
    public function actionEdit() {
        $user = user::getCurrent();
        if ($this->object->isWritableBy($user)) {
            $this->view="update";
        } else {
            $this->view="display";
        }
    }

    /**
     * Do action 'insert'
     * There is no "insert" for photos, so go straight to display
     */
    public function actionInsert() {
        $this->view="display";
    }

    /**
     * Do action 'lightbox'
     */
    public function actionLightbox() {
        $this->object->addTo(new album(user::getCurrent()->get("lightbox_id")));
        $this->view="display";
    }

    /**
     * Do action 'unlightbox'
     * Remove from lightbox
     */
    public function actionUnlightbox() {
        $this->object->removeFrom(new album(user::getCurrent()->get("lightbox_id")));
        $this->redirect="photos.php?" . $this->request->getPassedQueryString();
        $this->view="redirect";
    }

    /**
     * Do action 'new'
     * There is no "new" for photos, so go straight to display
     */
    public function actionNew() {
        $this->view="display";
    }

    /**
     * Do action 'rate'
     */
    public function actionRate() {
        $user=user::getCurrent();
        if (conf::get("feature.rating") && ($user->isAdmin() || $user->get("allow_rating"))) {
            $rating = $this->request->getPostVar("rating");
            $this->object->rate($rating);
        }
        breadcrumb::init();
        $link = html_entity_decode(breadcrumb::getLast()->getURL());
        if (!$link) {
            $link = "zoph.php";
        }
        // change to proper redirect via view
        redirect($link);

        $this->view="redirect";
    }

    /**
     * Do action 'update'
     */
    public function actionUpdate() {
        $user=user::getCurrent();
        if ($this->object->isWritableBy($user)) {
            $_deg = $this->request["_deg"];
            if (conf::get("rotate.enable") && ($_deg && $_deg != 0)) {
                $photo->lookup();
                try {
                    $photo->rotate($_deg);
                } catch (Exception $e) {
                    die($e->getMessage());
                }
            }
            if ($this->request["_thumbnail"]) {
                $photo->thumbnail();
            }
            unset($this->actionlinks["cancel"]); /** @todo Check if this works */
            unset($this->actionlinks["edit"]);

            $this->object->setFields($this->request->getRequestVars());
            // pass again for add people, categories, etc
            $this->object->updateRelations($this->request->getRequestVars(), "_id");
            $this->object->update();
            if (!empty($this->request->getPassedQueryString())) {
                redirect("photo.php?" . $this->request->getPassedQueryString(), "Update done");
            }
        }
        $this->view="display";
    }

    /**
     * Do action 'select'
     * Add a photo to the selection, first check if it's not already selected.
     * @todo the $_SESSION access should be refactored into a separate session class
     */
    public function actionSelect() {
        $selectKey=false;
        if (isset($_SESSION["selected_photo"]) && is_array($_SESSION["selected_photo"])) {
            $selectKey=array_search($this->object->getId(), $_SESSION["selected_photo"]);
        }
        if ($selectKey === false) {
            $_SESSION["selected_photo"][]=$this->object->getId();
        }
        $this->view="display";
    }
}
