<?php

use BrizyPlaceholders\ContentPlaceholder;
use BrizyPlaceholders\ContextInterface;

class BrizyPro_Content_Placeholders_Image extends Brizy_Content_Placeholders_Simple
{

    use Brizy_Content_Placeholders_ImageAttributesAware;

    /**
     * @param ContextInterface $context
     * @param ContentPlaceholder $contentPlaceholder
     * @return mixed|string|void
     */
    public function getValue(ContextInterface $context, ContentPlaceholder $contentPlaceholder)
    {
        $noImageurl = BRIZY_PRO_PLUGIN_URL . "/public/images/no-image.png";

        if ($entity = $context->getWpPost()) {
            $attributes = $contentPlaceholder->getAttributes();

            $attachmentId = $this->getAttachmentId($context, $contentPlaceholder);

            if (!$attachmentId || !wp_attachment_is_image($attachmentId)) {
                return $noImageurl;
            }

	        if ( empty( $attributes['cW'] ) && empty( $attributes['cH'] ) ) {
		        return wp_get_attachment_image_url( $attachmentId, 'full' );
	        }

            $thumbnailUid = get_post_meta($attachmentId, 'brizy_attachment_uid', true);

            if (!$thumbnailUid) {
                $thumbnailUid = $attachmentId;
            }

            $imageMeta = wp_get_attachment_metadata($attachmentId);

            if (!isset($imageMeta['height']) || $imageMeta['height'] == 0) {
                return $noImageurl;
            }

            $focalPoint = get_post_meta($attachmentId, 'brizy_attachment_focal_point', true);

            if (!$focalPoint) {
                $focalPoint = array('x' => 50, 'y' => 50);
            }

            list($ox, $oy, $nW, $nH, $cW, $cH) = $this->calculateImageOffsetByFocalPoint(
                (int)$imageMeta['width'],
                (int)$imageMeta['height'],
                (int)$attributes['cW'],
                (int)$attributes['cH'],
                $focalPoint['x'],
                $focalPoint['y']);

            $filterParams = array(
                'iW' => (int)$nW,
                'iH' => (int)$nH,
                'oX' => $ox,
                'oY' => $oy,
                'cW' => (int)$cW,
                'cH' => (int)$cH,
            );

            $params = array(
                Brizy_Editor::prefix('_media') => $thumbnailUid,
                Brizy_Editor::prefix('_crop') => http_build_query($filterParams)
            );

            return site_url('?' . http_build_query($params));
        } else {
            return $noImageurl;
        }
    }

    /**
     * @param $iW
     * @param $iH
     * @param $cW
     * @param $cH
     * @param $ofX
     * @param $ofY
     *
     * @return array
     */
    protected function calculateImageOffsetByFocalPoint($iW, $iH, $cW, $cH, $ofX, $ofY)
    {

        // check if the container sizes are valid
        if ($cW == 0) {
            $cW = (int)(($iW * $cH) / $iH);
        }

        if ($cH == 0) {
            $cH = (int)(($iH * $cW) / $iW);
        }


        $rC = (int)$cW / $cH;
        $rI = (int)$iW / $iH;
        $halfW = (int)$cW / 2;
        $halfH = (int)$cH / 2;

        if ($rI >= $rC) {
            $nW = $cH / $iH * $iW; // width after adjust to container size
            $nH = $cH; // height after adjust to container size
            $fX = (int)($nW * ($ofX / 100));

            if ($fX + $halfW > $nW) {
                $oX = $nW - $cW;
            } elseif ($fX - $halfW <= 0) {
                $oX = 0;
            } else {
                $oX = $fX - $halfW;
            }
            //$oX = $oX * $iH / $cH;
            $oY = 0;
        } else {
            $oX = 0;
            $nW = $cW; // width after adjust to container size
            $nH = $cW / $iW * $iH;
            $fY = (int)($nH * ($ofY / 100));

            if ($fY + $halfH > $nH) {
                $oY = $nH - $cH;
            } elseif ($fY - $halfH <= 0) {
                $oY = 0;
            } else {
                $oY = $fY - $halfH;
            }
            //$oY = $oY * $iW / $cW;
        }

        return array((int)$oX, (int)$oY, $nW, $nH, $cW, $cH);
    }


    /**
     * Get an attachment ID given a URL.
     *
     * @param string $url
     *
     * @return int Attachment ID on success, 0 on failure
     */
    protected function getAttachmentIdByUrl($url)
    {

        $attachment_id = 0;
        $dir = wp_upload_dir();

        if (false !== strpos($url, $dir['baseurl'] . '/')) { // Is URL in uploads directory?

            $file = basename($url);
            $query_args = array(
                'post_type' => 'attachment',
                'post_status' => 'inherit',
                'fields' => 'ids',
                'meta_query' => array(
                    array(
                        'value' => $file,
                        'compare' => 'LIKE',
                        'key' => '_wp_attachment_metadata',
                    ),
                )
            );

            $query = new WP_Query($query_args);

            if ($query->have_posts()) {

                foreach ($query->posts as $post_id) {
                    $meta = wp_get_attachment_metadata($post_id);
                    $original_file = basename($meta['file']);
                    $cropped_image_files = wp_list_pluck($meta['sizes'], 'file');
                    if ($original_file === $file || in_array($file, $cropped_image_files)) {
                        $attachment_id = $post_id;
                        break;
                    }
                }
            }
        }

        return $attachment_id;
    }

    public function getAttachmentId(Brizy_Content_Context $context, ContentPlaceholder $contentPlaceholder)
    {

        $attachmentId = parent::getValue($context, $contentPlaceholder);

        if (filter_var($attachmentId, FILTER_VALIDATE_URL)) {
            $attachmentId = $this->getAttachmentIdByUrl($attachmentId);
        }

        if (!$attachmentId || !wp_attachment_is_image($attachmentId)) {
            return null;
        }

        return $attachmentId;
    }
}