<?php

namespace WPaaS\StockPhotos;

use WPaaS\Plugin as WPaaS;

if ( ! defined( 'ABSPATH' ) ) {

	exit;

}

/**
 * Class API
 *
 * Handle fetching of image based on category from the D3 api
 */
final class API {

	const D3_ENDPOINT = 'https://categories.api.godaddy.com/v4';

	/**
	 * Holds the API endpoints
	 *
	 * @var string
	 */
	private $image_cat_url;
	private $category_api_url;

	/**
	 * Hold transient base namespace
	 *
	 * @const string
	 */
	private $transient_base                  = 'wpaas_stock_photos_api_v4_';
	private $transient_key_for_d3_categories = 'wpaas_stock_photos_d3_categories_v4';

	/**
	 * Image_API constructor.
	 */
	public function __construct() {

		$this->image_cat_url    = self::D3_ENDPOINT . '/categories/en_us/latest/%s/photos';
		$this->category_api_url = self::D3_ENDPOINT . '/categories/en_us/latest';

	}

	/**
	 * Retrieve json response from one category and store it as a transient for later use
	 *
	 * @param string $cat
	 * @return object array of objects
	 */
	public function get_images_by_cat( $cat ) {

		if ( false === ( $category = $this->get_api_cat( $cat ) ) ) {

			return [];

		}

		// Check if we have a transient cached response for that call
		if ( $data = get_transient( $this->transient_base . $category ) ) {

			return $data;

		}

		if ( false === ( $data = $this->fetch_images( $category ) ) ) {

			return [];

		}

		shuffle( $data );

		set_transient( $this->transient_base . $category, $data, HOUR_IN_SECONDS );

		return $data;

	}

	public function get_d3_choices() {

		$categories = $this->get_d3_categories();

		if ( ! $categories ) {

			return [];

		}

		/* uncomment this if we ever want to filter out "top level categories"

		// to help ensure the user chooses the most relevant category to their business,
		// let's not include "top level categories"
		$categories = array_filter( $categories, function( $category ) {

			return count( $category['parents'] ) > 0;

		} );
		*/

		uasort( $categories, function( $a, $b ) {

			$pop_a = $a['popularity'];
			$pop_b = $b['popularity'];

			return ( $pop_a === $pop_b ) ? 0 : ( $pop_a > $pop_b ? -1 : 1 );

		} );

		$categories = wp_list_pluck( $categories, 'display_name' );
		$popular    = array_slice( $categories, 0, 50 );
		$others     = array_slice( $categories, 50 );

		natcasesort( $others );

		$choices = array_diff_key(
			$popular + $others,
			array_flip(
				[
					'ayesha_curry_food',
					'conference_attendee',
					'dan_nonprofit',
					'diyfood',
					'elohim_music',
					'elohim_music_2',
					'elohim_music_3',
					'pedro',
					'personal_fooddrink',
					'tyson_manufacturing',
				]
			)
		);

		// Prepend an empty choice for Select2
		return [ '' => '' ] + $choices;

	}



	/**
	 * Get and cache D3 categories from their API endpoint
	 * see https://d3.godaddy.com/api/v1/categories/
	 *
	 * @return false if api error, otherwise assoc array of category object's "str_id" => category object
	 */
	public function get_d3_categories() {

		// Check if we have a transient cached response for that call
		if ( $data = get_transient( $this->transient_key_for_d3_categories ) ) {

			return $data;

		}

		if ( $data = $this->fetch_d3_categories() ) {

			// can use slower cache expiry since the category api endpoint is updated very infrequently
			set_transient( $this->transient_key_for_d3_categories, $data, DAY_IN_SECONDS );

		}

		return $data;

	}

	public function get_d3_categories_fallback() {

		$list = [
			'professional'         => __( 'Business / Finance / Law', 'stock-photos' ),
			'graphicdesign'        => __( 'Design / Art / Portfolio', 'stock-photos' ),
			'education'            => __( 'Education', 'stock-photos' ),
			'health'               => __( 'Health / Beauty', 'stock-photos' ),
			'constructionservices' => __( 'Home Services / Construction', 'stock-photos' ),
			'massmedia'            => __( 'Music / Movies / Entertainment', 'stock-photos' ),
			'nonprofit'            => __( 'Non-profit / Causes / Religious', 'stock-photos' ),
			'generic_outdoors'     => __( 'Other', 'stock-photos' ),
			'pets'                 => __( 'Pets / Animals', 'stock-photos' ),
			'realestate'           => __( 'Real Estate', 'stock-photos' ),
			'restaurants'          => __( 'Restaurant / Food', 'stock-photos' ),
			'personal_sports'      => __( 'Sports / Recreation', 'stock-photos' ),
			'auto'                 => __( 'Transportation / Automotive', 'stock-photos' ),
			'travelservices'       => __( 'Travel / Hospitality / Leisure', 'stock-photos' ),
			'weddingphotographers' => __( 'Wedding', 'stock-photos' ),
		];

		return $list;

	}

	/**
	 * Helper to fetch categories from the API
	 *
	 * As an implementation detail, does some post processing of the raw API json response
	 *
	 * @return false if api error, otherwise assoc array of category object's "str_id" => category object
	 */
	private function fetch_d3_categories() {

		$categories = $this->fetch( $this->category_api_url );

		if ( ! $categories ) {

			return;

		}

		$output = [];

		foreach ( $categories as $i => $cat ) {

			$output[ $cat->id ] = [
				'display_name' => $cat->name,
				'popularity'   => $cat->popularity,
			];

		}

		return $output;

	}

	/**
	 * Check if the current locale can use d3.
	 *
	 * @return bool
	 */
	public function is_d3_locale() {

		return in_array( get_locale(), [ 'en_US', 'en_CA' ], true );

	}

	/**
	 * Get api category slug
	 *
	 * @param string $slug
	 *
	 * @return bool|string
	 */
	private function get_api_cat( $slug ) {

		$d3_categories = $this->get_d3_categories();

		if ( ! $d3_categories && array_key_exists( $slug, $this->get_d3_categories_fallback() ) ) {

			return $slug;

		}

		$d3_categories['generic'] = true;

		return isset( $d3_categories[ $slug ] ) ? $slug : false;

	}

	/**
	 * Helper to fetch infomation from the api
	 *
	 * @param string $url
	 * @return array|bool|mixed|object
	 */
	private function fetch( $url ) {

		$response = wp_remote_get(
			$url,
			[
				'headers' => [
					'Accept'        => 'application/json',
					'Authorization' => 'Token ' . WPaaS::config( 'd3.token' ),
				],
			]
		);

		if ( is_wp_error( $response ) ) {

			return false;

		}

		$response = json_decode( wp_remote_retrieve_body( $response ) );

		return isset( $response->result ) ? $response->result : false;

	}

	/**
	 * Helper function to fetch stock images from the API.
	 *
	 * When the given category has no stock photos, this function will be
	 * responsible for fetching the parent category's stock photo as a fallback.
	 *
	 * @param string $category a valid "str_id" slug from the category API
	 *
	 * @return false if api error, otherwise array of objects from the api
	 */
	private function fetch_images( $category ) {

		$json = $this->fetch( sprintf( $this->image_cat_url, $category ) );

		if ( ! $json ) {

			return false;

		}

		if ( count( $json ) > 0 ) {

			return $json;

		}

		if ( empty( $json->parent_category ) ) {

			return [];

		}

		return $this->fetch_images( $json->parent_category );

	}

}
