<?php
namespace Depicter\Services;

use Averta\Core\Utility\Arr;
use Averta\WordPress\Utility\Sanitize;

class DocumentFontsV1Service
{
	/**
	 * @var array[]
	 */
	private $fonts = [];

	/**
	 * Get font families
	 *
	 * @param int      $documentId  The document ID to get belonging faces
	 * @param string   $type        Repository type of the font. `google`, `typescript`, ..
	 *
	 * @return int[]|string[]
	 */
	public function getFamilies( $documentId, $type = 'google' ) {
		return array_keys( $this->getFontsInfo( $documentId, $type ) );
	}

	/**
	 * Get collected fonts list
	 *
	 * @param int      $documentId  The document ID to get belonging faces
	 * @param string   $type        Repository type of the font. `google`, `typescript`, ..
	 *
	 * @return int[]|string[]
	 */
	public function getFontsInfo( $documentId, $type = 'google' ) {
		return ! empty( $this->fonts[ $documentId ][ $type ] ) ? $this->fonts[ $documentId ][ $type ] : [];
	}

	/**
	 * Get font faces
	 *
	 * @param int      $documentId  The document ID to get belonging faces
	 * @param string  $type        Repository type of the font. `google`, `typescript`, ..
	 *
	 * @return array
	 */
	public function getFontsLinkQuery( $documentId, $type = 'google' ) {
		if( empty( $this->fonts[ $documentId ][ $type ] ) ){
			return [];
		}

		$fontFaces = [];

		foreach ( $this->fonts[ $documentId ][ $type ] as $fontNameSlug => $fontInfo ) {

			if ( $fontNameSlug == 'inherit' ) {
				continue;
			}

			if( 'google' === $type && isset( $this->fonts[ $documentId ]['local'][ $fontNameSlug ] ) ){
				continue;
			}

			$weights = [];
			foreach ( $fontInfo['weights'] as $key => $weight ) {
				$weight = 'regular' == strtolower($weight) ? '400' : $weight;
				$weights[ $key ] = $weight;
			}

			// Sort weight number ascending
			ksort( $weights );

			// Make weight query string for current font
			$weightQuery = '';
			foreach ( $weights as $weightKey => $weight ){
				$weightQuery .= $weight . ',';
			}
			$weightQuery = rtrim($weightQuery, ',');

			// Collect font name and weights in a query string
			$fontFaces[] = $fontInfo['face'] . ':' . $weightQuery;
		}

		return $fontFaces;
	}

	/**
	 * Add a font to fonts list
	 *
	 * @param int          $documentId  The document ID that the font belongs to
	 * @param string       $fontName    Font family name
	 * @param string|array $fontWeight  Font weight
	 * @param string       $type        Repository type of the font. `google`, `typescript`, ..
	 */
	public function addFont( $documentId, $fontName, $fontWeight, $type = 'google' ) {
		if ( empty( $fontName ) ) {
			return;
		}

		$systemFonts = $this->systemFonts();
		if ( in_array( $fontName, $systemFonts ) ) {
			$type = 'system';
		}

		$fontName = str_replace( ['\"', '"'], ['', ''], trim( $fontName ) );
		$fontNameSlug = Sanitize::slug( $fontName );
		$fontWeight = (array) $fontWeight;

		$this->initFontForDocument( $documentId );

		if ( isset( $this->fonts[ $documentId ][ $type ][ $fontNameSlug ] ) ) {
			foreach ( $fontWeight as $weight ) {
				if ( !in_array( $weight, $this->fonts[ $documentId ][ $type ][ $fontNameSlug ]['weights'] ) ) {
					$this->fonts[ $documentId ][ $type ][ $fontNameSlug ]['weights'][] = $weight;
				}
			}
		} else {
			$this->fonts[ $documentId ][ $type ][ $fontNameSlug ] = [
				'family'    => $fontName,
				'face'      => str_replace( ' ', '+', $fontName ),
				'weights'   => $fontWeight
			];
		}
	}

	public function addLocalFont( $documentId, $fontName, $variants = [] ) {
		if ( empty( $fontName ) ) {
			return;
		}

		$fontName = str_replace( ['\"', '"'], ['', ''], trim( $fontName ) );
		$fontNameSlug = Sanitize::slug( $fontName );
		$variants = (array) $variants;

		if ( isset( $this->fonts[ $documentId ][ 'local' ][ $fontNameSlug ] ) ) {
			$this->fonts[ $documentId ][ 'local' ][ $fontNameSlug ]['variants'] = Arr::merge( $this->fonts[ $documentId ][ 'local' ][ $fontNameSlug ]['variants'], $variants );
		} else {
			$this->fonts[ $documentId ][ 'local' ][ $fontNameSlug ] = [
				'family'    => $fontName,
				'variants'  => $variants
			];
		}
	}

	/**
	 * Generate Css for loading local css fonts
	 *
	 * @param $documentId
	 *
	 * @return string
	 */
	public function getLocalFontsCss( $documentId ){
		$fontsCss = "";

		if( ! empty( $this->fonts[ $documentId ][ 'local' ] ) && is_array( $this->fonts[ $documentId ][ 'local' ] ) ){
			foreach( $this->fonts[ $documentId ][ 'local' ] as $key => $fontInfo ){
				// Generate font face css style only for local/website fonts which used in the document
				if ( ! empty( $this->fonts[ $documentId ]['google'] ) && ! in_array( $key, array_keys( $this->fonts[ $documentId ]['google'] ) ) ) {
					continue;
				}

				if( is_array( $fontInfo['variants'] ) ){
					foreach( $fontInfo['variants'] as $fontVariant ){
						$fontsCss .= "@font-face{\n";
						$fontsCss .= !empty( $fontInfo['family']   ) ? "\tfont-family:\"" . $fontInfo['family']    ."\";\n" : "";
						$fontsCss .= !empty( $fontVariant['style'] ) ? "\tfont-style:"    . $fontVariant['style']  .";\n" : "";
						$fontsCss .= !empty( $fontVariant['weight'] ) ? "\tfont-weight:"  . $fontVariant['weight'] .";\n" : "";
						$fontsCss .= "\tfont-display:fallback;\n";
						$fontsCss .= !empty( $fontVariant['src'] ) ? "\tsrc:". str_replace( '"', "'", $fontVariant['src'] ) .";\n" : "";
						$fontsCss .= "\tfont-stretch:normal;\n}\n";
					}
				}
			}
		}

		return $fontsCss;
	}

	protected function initFontForDocument( $documentId ){
		if( ! isset( $this->fonts[ $documentId ] ) ){
			$this->fonts[ $documentId ] = [
				'google' => []
			];
		}
	}

	/**
	 * Add list of fonts to fonts list
	 *
	 * @param int    $documentId  The document ID that fonts belong to
	 * @param array  $fontList
	 * @param string $type
	 */
	public function addFonts( $documentId, $fontList, $type = 'google' ) {
		if ( empty( $fontList ) ) {
			return;
		}

		foreach ( $fontList as $fontName => $fontWeight ){
			$this->addFont( $documentId, $fontName, $fontWeight, $type );
		}
	}

	/**
	 * Get system Fonts
	 *
	 * @return array
	 */
	public function systemFonts() {
		return [
			'Arial',
			'Helvetica',
			'Times New Roman',
			'Georgia',
			'Courier New',
			'Verdana',
			'Tahoma'
		];
	}

	/**
	 * Get fonts load link
	 *
	 * @param int    $documentId The document ID to get belonging faces
	 * @param string $type Repository type of the font. `google`, `typescript`, ..
	 *
	 * @return bool|string
	 */
	public function getFontsLink( $documentId, $type = 'google' ) {
		if ( $fontsQuery = $this->getFontsLinkQuery( $documentId, $type = 'google' ) ) {
			$fontsQuery = implode( "|", $fontsQuery );
			return 'https://fonts.googleapis.com/css?family=' . $fontsQuery . '&display=swap';
		}

		return '';
	}
}