<?php

declare(strict_types=1);

namespace PhpWA\Auth;

use InvalidArgumentException;
use PhpWA\Protocol\ProtocolVersion;

final class CompanionDeviceConfig
{
    /** @var ProtocolVersion */ private $version;
    /** @var string */ private $operatingSystem;
    /** @var string */ private $browserName;
    /** @var string */ private $countryCode;
    /** @var string */ private $languageCode;
    /** @var bool */ private $syncFullHistory;
    /** @var string|null */ private $pushName;

    public function __construct(
        ?ProtocolVersion $version = null,
        string $operatingSystem = 'Mac OS',
        string $browserName = 'Chrome',
        string $countryCode = 'US',
        string $languageCode = 'en',
        bool $syncFullHistory = true,
        ?string $pushName = null
    ) {
        foreach ([$operatingSystem, $browserName] as $value) {
            if ($value === '' || strlen($value) > 64 || preg_match('/^[A-Za-z0-9 ._()-]+$/D', $value) !== 1) {
                throw new InvalidArgumentException('Companion OS and browser names must be short printable identifiers.');
            }
        }
        if (preg_match('/^[A-Z]{2}$/D', $countryCode) !== 1 || preg_match('/^[a-z]{2,3}$/D', $languageCode) !== 1) {
            throw new InvalidArgumentException('Companion locale must use ISO language and country codes.');
        }
        if ($pushName !== null && ($pushName === '' || strlen($pushName) > 128 || preg_match('//u', $pushName) !== 1
            || preg_match('/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/', $pushName) === 1)) {
            throw new InvalidArgumentException('Companion push name is invalid.');
        }
        $this->version = $version ?? ProtocolVersion::current();
        $this->operatingSystem = $operatingSystem;
        $this->browserName = $browserName;
        $this->countryCode = $countryCode;
        $this->languageCode = $languageCode;
        $this->syncFullHistory = $syncFullHistory;
        $this->pushName = $pushName;
    }

    public function version(): ProtocolVersion { return $this->version; }
    public function operatingSystem(): string { return $this->operatingSystem; }
    public function browserName(): string { return $this->browserName; }
    public function countryCode(): string { return $this->countryCode; }
    public function languageCode(): string { return $this->languageCode; }
    public function syncFullHistory(): bool { return $this->syncFullHistory; }
    public function pushName(): ?string { return $this->pushName; }
}
