<?php

declare(strict_types=1);

/**
 * @author Amasty Team
 * @copyright Copyright (c) Amasty (https://www.amasty.com)
 * @package Lazy Load for Magento 2 (System)
 */

namespace Amasty\LazyLoad\Model\LazyScript;

use Magento\Framework\App\ObjectManager;
use Magento\Framework\View\Helper\SecureHtmlRenderer;

class NativeJs implements LazyScriptInterface
{
    public const SCRIPT = '!(function(){var h=window.addEventListener||function(n,f){window.attachEvent("on"+n,f)}' .
    ',removeEventListener=window.removeEventListener||function(n,f,b){window.detachEvent("on"+n,f)};' .
    'var j={cache:[],mobileScreenSize:500,observersAdded:false,attributes:{data_src:"data-amsrc",data_srcset:' .
    '"data-amsrcset",data_src_mobile:"data-src-mobile"},addObservers:function(){if(!this.observersAdded){h("scroll",' .
    'j.throttledLoad);h("resize",j.throttledLoad);this.observersAdded=true}},removeObservers:function()' .
    '{removeEventListener("scroll",j.throttledLoad,false);removeEventListener("resize",j.throttledLoad,false);' .
    'this.observersAdded=false},throttleTimer:new Date().getTime(),throttledLoad:function(){var a=new Date().getTime' .
    '();if((a-j.throttleTimer)>=200){j.throttleTimer=a;j.loadVisibleImages()}},loadVisibleImages:function(){var ' .
    'a=window.pageYOffset||document.documentElement.scrollTop;var b=window.innerHeight||document.documentElement.' .
    'clientHeight;var c={min:a-200,max:a+b+200};var i=0;while(i<j.cache.length){var d=j.cache[i];var e=getOffsetTop' .
    '(d);var f=d.height||0;if((e>=c.min-f)&&(e<=c.max)){var g=d.getAttribute(this.attributes.data_src_mobile);' .
    'd.onload=function(){this.className=this.className.replace(/(^|\s+)lazy-load(\s+|$)/,"$1lazy-loaded$2")};' .
    'if(g&&screen.width<=j.mobileScreenSize){d.src=g}else{const srcImage=d.getAttribute(this.attributes.data_src);' .
    'if(srcImage!==null){d.src=srcImage}const srcsetImage=d.getAttribute(this.attributes.data_srcset);' .
    'if(srcsetImage!==null){d.srcset=srcsetImage}}d.removeAttribute(this.attributes.data_srcset);' .
    'd.removeAttribute(this.attributes.data_src);d.removeAttribute(this.attributes.data_src_mobile);' .
    'j.cache.splice(i,1);continue}i++}if(j.cache.length===0){j.removeObservers()}},init:function(){' .
    'if(!document.querySelectorAll){document.querySelectorAll=function(a){var b=document,head=b.documentElement.' .
    'firstChild,styleTag=b.createElement("STYLE");head.appendChild(styleTag);b.__qsaels=[];styleTag.styleSheet.' .
    'cssText=a+"{x:expression(document.__qsaels.push(this))}";window.scrollBy(0,0);return b.__qsaels}}' .
    'var c=document.querySelectorAll(`img[${this.attributes.data_src}],img[${this.attributes.data_srcset}]`);' .
    'for(var i=0;i<c.length;i++){var d=c[i];if(j.cache.indexOf(d)==-1){j.cache.push(d)}}j.addObservers();' .
    'j.loadVisibleImages()}};function getOffsetTop(a){var b=0;if(a.offsetParent){do{b+=a.offsetTop}while(' .
    'a=a.offsetParent);return b}}j.init();window.amlazycallback=j.init.bind(j)})();';

    /**
     * @var SecureHtmlRenderer
     */
    private $secureRenderer;

    public function __construct(
        ?SecureHtmlRenderer $secureRenderer = null // TODO move to not optional
    ) {
        $this->secureRenderer = $secureRenderer ?? ObjectManager::getInstance()->get(SecureHtmlRenderer::class);
    }

    public function getName(): string
    {
        return (string)__('Native JavaScript Lazy Script');
    }

    public function getType(): string
    {
        return 'native';
    }

    public function getCode(): string
    {
        return $this->secureRenderer->renderTag(
            'script',
            [],
            self::SCRIPT,
            false
        );
    }

    public function getSupportedTags(): array
    {
        return ['img'];
    }
}
