<?php declare(strict_types=1);
/**
 * Hummingbird Anime List Client
 *
 * An API client for Kitsu to manage anime and manga watch lists
 *
 * PHP version 7.1
 *
 * @package     HummingbirdAnimeClient
 * @author      Timothy J. Warren <tim@timshomepage.net>
 * @copyright   2015 - 2018  Timothy J. Warren
 * @license     http://www.opensource.org/licenses/mit-license.html  MIT License
 * @version     4.1
 * @link        https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient
 */

namespace Aviat\AnimeClient\Model;

use Aviat\AnimeClient\Types\{Config, UndefinedPropertyException};

use Aviat\Ion\ConfigInterface;
use Aviat\Ion\Di\ContainerAware;
use Aviat\Ion\StringWrapper;

/**
 * Model for handling settings control panel
 */
final class Settings {
	use ContainerAware;
	use StringWrapper;

	private $config;

	/**
	 * Map the config values to types and form fields
	 */
	private const SETTINGS_MAP = [
		'anilist' => [

		],
		'config' => [
			'kitsu_username' => [
				'type' => 'string',
				'title' => 'Kitsu Username',
				'default' => '',
				'readonly' => TRUE,
				'description' => 'Username of the account to pull list data from.',
			],
			'whose_list' => [
				'type' => 'string',
				'title' => 'Whose List',
				'default' => 'Somebody',
				'readonly' => TRUE,
				'description' => 'Name of the owner of the list data.',
			],
			'show_anime_collection' => [
				'type' => 'boolean',
				'title' => 'Show Anime Collection',
				'default' => FALSE,
				'description' => 'Should the anime collection be shown?',
			],
			'show_manga_collection' => [
				'type' => 'boolean',
				'title' => 'Show Manga Collection',
				'default' => FALSE,
				'description' => 'Should the manga collection be shown?',
			],
			'asset_path' => [
				'type' => 'string',
				'display' => FALSE,
				'description' => 'Path to public directory, where images/css/javascript are located',
			],
			'default_list' => [
				'type' => 'select',
				'title' => 'Default List',
				'description' => 'Which list to show by default.',
				'options' => [
					'Anime' => 'anime',
					'Manga' => 'manga',
				],
			],
			'default_anime_list_path' => [ //watching|plan_to_watch|on_hold|dropped|completed|all
				'type' => 'select',
				'title' => 'Default Anime List Section',
				'description' => 'Which part of the anime list to show by default.',
				'options' => [
					'Watching' => 'watching',
					'Plan to Watch' => 'plan_to_watch',
					'On Hold' => 'on_hold',
					'Dropped' => 'dropped',
					'Completed' => 'completed',
					'All' => 'all',
				]
			],
			'default_manga_list_path' => [ //reading|plan_to_read|on_hold|dropped|completed|all
				'type' => 'select',
				'title' => 'Default Manga List Section',
				'description' => 'Which part of the manga list to show by default.',
				'options' => [
					'Reading' => 'reading',
					'Plan to Read' => 'plan_to_read',
					'On Hold' => 'on_hold',
					'Dropped' => 'dropped',
					'Completed' => 'completed',
					'All' => 'all',
				]
			]
		],
		'cache' => [
			'driver' => [
				'type' => 'select',
				'title' => 'Cache Type',
				'description' => 'The Cache backend',
				'options' => [
					'APCu' => 'apcu',
					'Memcached' => 'memcached',
					'Redis' => 'redis',
					'No Cache' => 'null'
				],
			],
			'connection' => [
				'type' => 'subfield',
				'title' => 'Connection',
				'fields' => [
					'host' => [
						'type' => 'string',
						'title' => 'Cache Host',
						'description' => 'Host of the cache backend to connect to',
					],
					'port' => [
						'type' => 'string',
						'title' => 'Cache Port',
						'description' => 'Port of the cache backend to connect to',
					],
					'password' => [
						'type' => 'string',
						'title' => 'Cache Password',
						'description' => 'Password to connect to cache backend',
					],
					'database' => [
						'type' => 'string',
						'title' => 'Cache Database',
						'description' => 'Cache database number for Redis',
					],
				],
			],
		],
		'database' => [
			'type' => [
				'type' => 'select',
				'title' => 'Database Type',
				'options' => [
					'MySQL' => 'mysql',
					'PostgreSQL' => 'pgsql',
					'SQLite' => 'sqlite',
				],
				'description' => 'Type of database to connect to',
			],
			'host' => [
				'type' => 'string',
				'title' => 'Host',
				'description' => 'The host of the database server',
			],
			'user' => [
				'type' => 'string',
				'title' => 'User',
				'description' => 'Database connection user',
			],
			'pass' => [
				'type' => 'string',
				'title' => 'Password',
				'description' => 'Database connection password'
			],
			'port' => [
				'type' => 'string',
				'title' => 'Port',
				'description' => 'Database connection port'
			],
			'database' => [
				'type' => 'string',
				'title' => 'Database Name',
				'description' => 'Name of the database/schema to connect to',
			],
			'file' => [
				'type' => 'string',
				'title' => 'Database File',
				'description' => 'Path to the database file, if required by the current database type.'
			],
		],
	];

	public function __construct(ConfigInterface $config)
	{
		$this->config = $config;
	}

	public function getSettings()
	{
		$settings = [
			'config' => [],
		];

		foreach(static::SETTINGS_MAP as $file => $values)
		{
			if ($file === 'config')
			{
				$keys = array_keys($values);
				foreach($keys as $key)
				{
					$settings['config'][$key] = $this->config->get($key);
				}
			}
			else
			{
				$settings[$file] = $this->config->get($file);
			}
		}

		return $settings;
	}

	public function getSettingsForm()
	{
		$output = [];

		$settings = $this->getSettings();

		foreach($settings as $file => $values)
		{
			foreach(static::SETTINGS_MAP[$file] as $key => $value)
			{
				if ($value['type'] === 'subfield')
				{
					foreach($value['fields'] as $k => $field)
					{
						$value['fields'][$k]['value'] = $values[$key][$k] ?? '';
						$value['fields'][$k]['display'] = TRUE;
						$value['fields'][$k]['readonly'] = FALSE;
						$value['fields'][$k]['disabled'] = FALSE;
					}
				}

				if (is_scalar($values[$key]))
				{
					$value['value'] = $values[$key];
				}

				foreach (['readonly', 'disabled'] as $flag)
				{
					if ( ! array_key_exists($flag, $value))
					{
						$value[$flag] = FALSE;
					}
				}

				if ( ! array_key_exists('display', $value))
				{
					$value['display'] = TRUE;
				}

				$output[$file][$key] = $value;
			}
		}

		return $output;
	}

	public function validateSettings(array $settings): bool
	{
		try
		{
			new Config($settings);
		}
		catch (UndefinedPropertyException $e)
		{
			return FALSE;
		}

		return TRUE;
	}

	public function saveSettingsFile()
	{

	}
}