<?php
/**
 * Pimcore
 *
 * This source file is subject to the GNU General Public License version 3 (GPLv3)
 * For the full copyright and license information, please view the LICENSE.md and gpl-3.0.txt
 * files that are distributed with this source code.
 *
 * @copyright  Copyright (c) 2009-2016 pimcore GmbH (http://www.pimcore.org)
 * @license    http://www.pimcore.org/license     GNU General Public License version 3 (GPLv3)
 */

namespace Pimcore\Tool;

class DeviceDetector {

    /**
     * @var array
     */
    protected $validDeviceTypes = ["phone","tablet","desktop"];

    /**
     * @var null|string
     */
    protected $default = "desktop";

    /**
     * @var bool
     */
    protected $isPhone = false;

    /**
     * @var bool
     */
    protected $isDesktop = false;

    /**
     * @var bool
     */
    protected $isTablet = false;

    /**
     * @var null|DeviceDetector
     */
    protected static $instance = null;

    /**
     * @var bool
     */
    protected $determinedDeviceType = false;

    /**
     * @var bool
     */
    protected $wasUsed = false;

    /**
     * @param null $default
     * @return DeviceDetector
     */
    public static function getInstance($default = null) {
        if(!self::$instance) {
            self::$instance = new self($default);
        }

        return self::$instance;
    }

    /**
     * @param null $default
     */
    public function __construct($default = null) {
        if($default && in_array($default, ["desktop","mobile","tablet"])) {
            $this->default = $default;
        }
    }

    /**
     * @return bool
     */
    public function isDesktop() {
        $this->determineDeviceType();
        return $this->isDesktop;
    }

    /**
     * @return bool
     */
    public function isTablet() {
        $this->determineDeviceType();
        return $this->isTablet;
    }

    /**
     * @return bool
     */
    public function isPhone() {
        $this->determineDeviceType();
        return $this->isPhone;
    }

    /**
     * @return bool
     */
    public function wasUsed() {
        return $this->wasUsed;
    }

    /**
     * @param $wasUsed
     */
    public function setWasUsed($wasUsed) {
        $this->wasUsed = $wasUsed;
    }

    /**
     * @return string
     */
    public function getDevice() {
        foreach($this->validDeviceTypes as $deviceType) {
            if($this->{"is".ucfirst($deviceType)}()) {
                return $deviceType;
            }
        }

        return $this->default;
    }

    /**
     * @return string
     */
    public function __toString() {
        return $this->getDevice();
    }

    /**
     *
     */
    protected function determineDeviceType () {

        $this->setWasUsed(true);

        if($this->determinedDeviceType) {
            return;
        }

        $userAgent = $_SERVER['HTTP_USER_AGENT'];

        $type = null;

        // android devices
        if(stripos($userAgent, "android") !== false) {
            // unfortunately there are still android tablet that contain "Mobile" in user-agent, damn!
            if(stripos($userAgent, "mobile") !== false) {
                $type = "phone";
            } else {
                $type = "tablet";
            }
        }

        // ios devices
        if(stripos($userAgent, "ipad") !== false) {
            $type = "tablet";
        }
        if(stripos($userAgent, "iphone") !== false) {
            $type = "phone";
        }

        // all other vendors, like blackberry, ...
        if(!$type && stripos($userAgent, "mobile") !== false) {
            $type = "phone";
        }

        // default is desktop
        if(!$type) {
            $type = $this->default;
        }

        // check for a forced type
        $typeForced = null;
        if(isset($_REQUEST["forceDeviceType"]) && $_REQUEST["forceDeviceType"]) {
            $typeForced = $_REQUEST["forceDeviceType"];
        }

        if(isset($_COOKIE["forceDeviceType"]) && $_COOKIE["forceDeviceType"]) {
            $typeForced = $_COOKIE["forceDeviceType"];
        }

        if($typeForced) {
            if(in_array($typeForced, $this->validDeviceTypes)) {
                $type = $typeForced;

                if(!isset($_COOKIE["forceDeviceType"])) {
                    setcookie("forceDeviceType", $type);
                }
            }
        }

        $this->{"is".ucfirst($type)} = true;
        $this->determinedDeviceType = true;
    }
}