<?php

/*
 * This file is part of the AuthStack project.
 *
 * (c) Buckhill Ltd <development@buckhill.co.uk>
 *
 * This source file is subject to the Buckhill license that is bundled
 * with this source code in the file LICENSE.
 */

namespace AuthStack\Driver\User;


use AuthStack\Driver\Model\User;
use AuthStack\TwoFactor\Model\SecurityKey;
use AuthStack\Driver\Errors\NoProvisionedUserError;
use AuthStack\TwoFactor\Collection\KeyCollectionInterface;

abstract class AbstractUser implements UserInterface
{
    protected $authstack_id;
    protected $authsource_id;
    protected $key_collection;
    protected $username;
    protected $pkey = null;
    protected $pkey_value = null;
    protected $is_admin = false;
    protected $attributes;
    protected $provisioned;

    /**
     * @param $id
     *
     * @return $this
     */
    public function setAuthstackID($id)
    {
        $this->authstack_id = $id;

        return $this;
    }

    /**
     * @return int
     */
    public function getAuthstackID()
    {
        return $this->authstack_id;
    }

    /**
     * @param $id
     *
     * @return $this
     */
    public function setAuthsourceID($id)
    {
        $this->authsource_id = $id;

        return $this;
    }

    /**
     * @return int
     */
    public function getAuthsourceID()
    {
        return $this->authsource_id;
    }

    /**
     * @param User $provisioned
     *
     * @return $this
     */
    public function setProvisionedUser(User $provisioned)
    {
        $this->provisioned = $provisioned;

        return $this;
    }

    /**
     * @return User
     *
     * @throws NoProvisionedUserError
     */
    public function getProvisionedUser()
    {
        if (!$this->provisioned instanceof User) {
            throw new NoProvisionedUserError('No ProvisionedUser object available. Did you authenticate with the authsource?');
        }

        return $this->provisioned;
    }

    /**
     * @param KeyCollectionInterface $collection
     *
     * @return $this
     */
    public function setKeyCollection(KeyCollectionInterface $collection)
    {
        $this->key_collection = $collection;

        return $this;
    }

    /**
     * @return KeyCollectionInterface|null
     */
    public function getKeyCollection()
    {
        return $this->key_collection;
    }

    /**
     * @param $username
     *
     * @return $this
     */
    public function setUsername($username)
    {
        $this->username = $username;

        return $this;
    }

    /**
     * @return mixed
     */
    public function getUsername()
    {
        return $this->username;
    }

    /**
     * @return string|null
     */
    public function getPrimaryKeyValue()
    {
        return $this->pkey_value;
    }

    /**
     * @return bool
     */
    public function hasTwoFactorKeys()
    {
        $collection = $this->getKeyCollection();

        if (!$collection instanceof KeyCollectionInterface) {
            return false;
        }

        return (bool) $collection->count();
    }

    /**
     * @return bool
     */
    public function hasU2FKeys()
    {
        if (!$this->hasTwoFactorKeys()) {
            return false;
        }

        $collection = $this->getKeyCollection();

        return $collection->hasU2F();
    }

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

    /**
     * @return $this
     */
    public function setAdmin()
    {
        $this->is_admin = true;

        return $this;
    }

    /**
     * @param $key_id
     *
     * @return bool
     */
    public function removeSecurityKey($key_id)
    {
        $result = false;

        try {
            $model = SecurityKey::where('user_id', $this->getAuthstackID())->where('key_id', $key_id)->firstOrFail();

            $result = $model->delete();
        } catch (\Exception $e) {
        }

        return $result;
    }


    /**
     * @param bool $object
     *
     * @return \DateTimeZone|string
     */
    public function getTimeZone($object = false)
    {
        $tz = $this->getProvisionedUser()->getTimeZone();

        if($object)
        {
            $tz = new \DateTimeZone($tz);
        }

        return $tz;
    }


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


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


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


    /**
     * @return array
     */
    public function toArray()
    {
        return $this->attributes;
    }
}
