<?php

namespace LdapRecord\Models\Attributes;

use Carbon\Carbon;
use Carbon\CarbonInterface;
use DateTime;
use LdapRecord\LdapRecordException;
use LdapRecord\Utilities;

class Timestamp
{
    /**
     * The current timestamp type.
     *
     * @var string
     */
    protected $type;

    /**
     * The available timestamp types.
     *
     * @var array
     */
    protected $types = [
        'ldap',
        'windows',
        'windows-int',
    ];

    /**
     * Constructor.
     *
     * @param string $type
     *
     * @throws LdapRecordException
     */
    public function __construct($type)
    {
        $this->setType($type);
    }

    /**
     * Set the type of timestamp to convert from / to.
     *
     * @param string $type
     *
     * @throws LdapRecordException
     */
    public function setType($type)
    {
        if (! in_array($type, $this->types)) {
            throw new LdapRecordException("Unrecognized LDAP date type [$type]");
        }

        $this->type = $type;
    }

    /**
     * Converts the value to an LDAP date string.
     *
     * @param mixed $value
     *
     * @throws LdapRecordException
     *
     * @return float|string
     */
    public function fromDateTime($value)
    {
        $value = is_array($value) ? reset($value) : $value;

        // If the value is being converted to a windows integer format but it
        // is already in that format, we will simply return the value back.
        if ($this->type == 'windows-int' && $this->valueIsWindowsIntegerType($value)) {
            return $value;
        }
        // If the value is numeric, we will assume it's a UNIX timestamp.
        elseif (is_numeric($value)) {
            $value = Carbon::createFromTimestamp($value);
        }
        // If a string is given, we will pass it into a new carbon instance.
        elseif (is_string($value)) {
            $value = Carbon::parse($value);
        }
        // If a date object is given, we will convert it to a carbon instance.
        elseif ($value instanceof DateTime) {
            $value = Carbon::instance($value);
        }

        switch ($this->type) {
            case 'ldap':
                $value = $this->convertDateTimeToLdapTime($value);
                break;
            case 'windows':
                $value = $this->convertDateTimeToWindows($value);
                break;
            case 'windows-int':
                $value = $this->convertDateTimeToWindowsInteger($value);
                break;
            default:
                throw new LdapRecordException("Unrecognized date type [{$this->type}]");
        }

        return $value;
    }

    /**
     * Determine if the value given is in Windows Integer (NTFS Filetime) format.
     *
     * @param int|string $value
     *
     * @return bool
     */
    protected function valueIsWindowsIntegerType($value)
    {
        return is_numeric($value) && strlen((string) $value) === 18;
    }

    /**
     * Converts the LDAP timestamp value to a Carbon instance.
     *
     * @param mixed $value
     *
     * @throws LdapRecordException
     *
     * @return Carbon|false
     */
    public function toDateTime($value)
    {
        $value = is_array($value) ? reset($value) : $value;

        if ($value instanceof CarbonInterface || $value instanceof DateTime) {
            return Carbon::instance($value);
        }

        switch ($this->type) {
            case 'ldap':
                $value = $this->convertLdapTimeToDateTime($value);
                break;
            case 'windows':
                $value = $this->convertWindowsTimeToDateTime($value);
                break;
            case 'windows-int':
                $value = $this->convertWindowsIntegerTimeToDateTime($value);
                break;
            default:
                throw new LdapRecordException("Unrecognized date type [{$this->type}]");
        }

        return $value instanceof DateTime ? Carbon::instance($value) : $value;
    }

    /**
     * Converts standard LDAP timestamps to a date time object.
     *
     * @param string $value
     *
     * @return DateTime|bool
     */
    protected function convertLdapTimeToDateTime($value)
    {
        return DateTime::createFromFormat(
            strpos($value, 'Z') !== false ? 'YmdHis\Z' : 'YmdHisT',
            $value
        );
    }

    /**
     * Converts date objects to a standard LDAP timestamp.
     *
     * @param DateTime $date
     *
     * @return string
     */
    protected function convertDateTimeToLdapTime(DateTime $date)
    {
        return $date->format(
            $date->getOffset() == 0 ? 'YmdHis\Z' : 'YmdHisO'
        );
    }

    /**
     * Converts standard windows timestamps to a date time object.
     *
     * @param string $value
     *
     * @return DateTime|bool
     */
    protected function convertWindowsTimeToDateTime($value)
    {
        return DateTime::createFromFormat(
            strpos($value, '0Z') !== false ? 'YmdHis.0\Z' : 'YmdHis.0T',
            $value
        );
    }

    /**
     * Converts date objects to a windows timestamp.
     *
     * @param DateTime $date
     *
     * @return string
     */
    protected function convertDateTimeToWindows(DateTime $date)
    {
        return $date->format(
            $date->getOffset() == 0 ? 'YmdHis.0\Z' : 'YmdHis.0O'
        );
    }

    /**
     * Converts standard windows integer dates to a date time object.
     *
     * @param int $value
     *
     * @throws \Exception
     *
     * @return DateTime|bool
     */
    protected function convertWindowsIntegerTimeToDateTime($value)
    {
        // ActiveDirectory dates that contain integers may return
        // "0" when they are not set. We will validate that here.
        if (! $value) {
            return false;
        }

        return (new DateTime())->setTimestamp(
            Utilities::convertWindowsTimeToUnixTime($value)
        );
    }

    /**
     * Converts date objects to a windows integer timestamp.
     *
     * @param DateTime $date
     *
     * @return float
     */
    protected function convertDateTimeToWindowsInteger(DateTime $date)
    {
        return Utilities::convertUnixTimeToWindowsTime($date->getTimestamp());
    }
}
