<?php

namespace SugarCalendarBookings\Calendar\Admin;

use SugarCalendarBookings\Support\Helpers\Helpers;

/**
 * Calendar screen options.
 *
 * @since 1.0.0
 */
class CalendarScreenOptions {

	/**
	 * Options user meta key.
	 *
	 * @since 1.0.0
	 *
	 * @var string
	 */
	const META_KEY = 'sugar_calendar_bookings_calendar_screen_options';

	/**
	 * Get defaults.
	 *
	 * @since 1.0.0
	 * @since 1.3.0 Add 'view_mode' option.
	 *
	 * @return array[]
	 */
	private function get_defaults() {

		return [
			'view_mode'      => 'agenda',
			'hidden_columns' => [
				'month'  => [],
				'week'   => [],
				'day'    => [],
				'agenda' => [],
			],
		];
	}

	/**
	 * Recursively merge options.
	 *
	 * @since 1.0.0
	 *
	 * @param array $input    Input options.
	 * @param array $defaults Default options.
	 *
	 * @return array
	 */
	private function merge_options( $input, $defaults ) {

		$result = $defaults;

		foreach ( $input as $key => $value ) {
			if (
				is_array( $value ) &&
				Helpers::is_associative( $value ) &&
				isset( $result[ $key ] ) &&
				is_array( $result[ $key ] ) &&
				Helpers::is_associative( $result[ $key ] )
			) {
				// Both values are arrays, merge them recursively.
				$result[ $key ] = $this->merge_options( $value, $result[ $key ] );
			} else {
				// Input value overwrites default value.
				$result[ $key ] = $value;
			}
		}

		return $result;
	}

	/**
	 * Get option by key.
	 *
	 * @since 1.0.0
	 *
	 * @param string $key      Option key.
	 * @param mixed  $defaults Option default.
	 *
	 * @return mixed
	 */
	public function get( $key = null, $defaults = null ) {

		$data = get_user_meta( get_current_user_id(), static::META_KEY, true );
		$data = ! empty( $data ) ? $data : [];
		$data = $this->merge_options( $data, $this->get_defaults() );

		if ( $key !== null ) {
			return $data[ $key ] ?? $defaults;
		}

		return $data;
	}

	/**
	 * Update options.
	 *
	 * @since 1.0.0
	 *
	 * @param array $options Options array.
	 *
	 * @return void
	 */
	public function update( $options ) {

		$data = $this->merge_options( $options, $this->get() );

		update_user_meta( get_current_user_id(), static::META_KEY, $data );
	}

	/**
	 * Get the saved view mode.
	 *
	 * @since 1.3.0
	 *
	 * @return string
	 */
	public function get_view_mode() {

		return $this->get( 'view_mode', 'agenda' );
	}

	/**
	 * Set view mode if it differs from current saved value.
	 *
	 * @since 1.3.0
	 *
	 * @param string $mode View mode to save.
	 *
	 * @return void
	 */
	public function set_view_mode( $mode ) {

		if ( $mode !== $this->get_view_mode() ) {
			$this->update( [ 'view_mode' => $mode ] );
		}
	}
}
