package me.qwq.doghouse.flexmark.ext.lazyimg;

import java.util.Collections;
import java.util.Set;

import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.text.StringEscapeUtils;
import org.jetbrains.annotations.NotNull;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.vladsch.flexmark.ast.Image;
import com.vladsch.flexmark.html.HtmlRenderer;
import com.vladsch.flexmark.html.HtmlWriter;
import com.vladsch.flexmark.html.renderer.NodeRenderer;
import com.vladsch.flexmark.html.renderer.NodeRendererContext;
import com.vladsch.flexmark.html.renderer.NodeRendererFactory;
import com.vladsch.flexmark.html.renderer.NodeRenderingHandler;
import com.vladsch.flexmark.util.data.DataHolder;
import lombok.extern.slf4j.Slf4j;
import me.qwq.doghouse.entity.Asset;
import me.qwq.doghouse.enums.FileTypeEnum;
import me.qwq.doghouse.service.AssetService;
import me.qwq.doghouse.util.SpringContextHolder;

@Slf4j
public class LazyImgNodeRenderer implements NodeRenderer {

    static AssetService assetService = SpringContextHolder.getBean(AssetService.class);

    final LazyImgOptions options;
    
    public LazyImgNodeRenderer(DataHolder options) {
        this.options = new LazyImgOptions(options);
    }
    
    @Override
    public Set<NodeRenderingHandler<?>> getNodeRenderingHandlers() {
        return Collections.singleton(new NodeRenderingHandler<>(Image.class, this::render));
    }
    
    private void render(Image node, NodeRendererContext context, HtmlWriter html) {
        String url = node.getUrl().unescape();
        String altText = node.getText().toString();
        if (context.getOptions().getAll().getOrDefault(HtmlRenderer.ESCAPE_HTML, false).equals(true)) {
            altText = StringEscapeUtils.escapeHtml4(altText);
        }
        
        // query asset database to confirm image size
        Asset asset = assetService.getOne(
                new LambdaQueryWrapper<Asset>()
                .eq(Asset::getPath, url).eq(Asset::getFileType, FileTypeEnum.IMAGE));
        String w = asset == null ? null : asset.getImageWidth() != null ? asset.getImageWidth().toString() : null;
        String h = asset == null ? null : asset.getImageHeight() != null ? asset.getImageHeight().toString() : null;
        
        
        /** 形成形如如下的包裹
         <picture>
             <img data-src="example.jpg" loading="lazy" alt="test"/>
             <noscript>
                 <img src="example.jpg" alt="test"/>
             </noscript>
         </picture>
         */
        html
        .attr("class", "picture-lazy")
        .withAttr()
        .tag("picture")
            .attr("src", url)
            .attr("alt", altText)
            .attr("loading", "lazy");
        
        if (ObjectUtils.anyNotNull(w, h)) {
            html.attr("width", w)
                .attr("height", h);
        }
        
        html.withAttr().tag("img").closeTag("img") // lazy img
            .closeTag("picture")  // close picture
            .line();
    }
    
    public static class Factory implements NodeRendererFactory {
        @NotNull
        @Override
        public NodeRenderer apply(@NotNull DataHolder options) {
            return new LazyImgNodeRenderer(options);
        }
    }
}
