package com.atlassian.confluence.extra.amazon;

import com.atlassian.renderer.v2.macro.BaseMacro;
import com.atlassian.renderer.v2.macro.MacroException;
import com.atlassian.renderer.v2.macro.ResourceAware;
import com.atlassian.renderer.v2.macro.code.XmlFormatter;
import com.atlassian.renderer.v2.RenderMode;
import com.atlassian.renderer.RenderContext;
import com.atlassian.confluence.util.http.HttpRetrievalService;
import com.atlassian.confluence.util.http.HttpResponse;
import com.atlassian.confluence.util.GeneralUtil;
import com.atlassian.confluence.util.VelocityUtils;
import com.atlassian.confluence.renderer.radeox.macros.MacroUtils;
import com.opensymphony.util.TextUtils;

import java.util.Map;
import java.io.IOException;

import org.jdom.input.SAXBuilder;
import org.jdom.JDOMException;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.output.XMLOutputter;
import org.jdom.output.Format;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.exception.ResourceNotFoundException;
import org.apache.log4j.Category;

public class AmazonAsinMacro extends BaseMacro
{
    public static final Category log = Category.getInstance(AmazonAsinMacro.class);
    private static final String BASE_AMAZON_URL = "http://webservices.amazon.com/onca/xml?Service=AWSECommerceService";
    private static final String MY_AMAZON_ID = "1163JES54SFRXDA3J202";

    private HttpRetrievalService httpRetrievalService;

    public boolean isInline()
    {
        return false;
    }

    public boolean hasBody()
    {
        return false;
    }

    public RenderMode getBodyRenderMode()
    {
        return RenderMode.NO_RENDER;
    }

    public String execute(Map parameters, String body, RenderContext renderContext) throws MacroException
    {
        String asin = (String) parameters.get("0");

        if (!TextUtils.stringSet(asin))
            throw new MacroException("Could not find an ASIN to look up. Example usage: {asin:0375501843}");

        try
        {
            String searchUrl = makeSearchUrl(asin);
            HttpResponse response = httpRetrievalService.get(searchUrl);
            return toHtml(response);
        }
        catch (Exception e)
        {
            throw new MacroException(e.getMessage());
        }
    }

    private String toHtml(HttpResponse response) throws IOException, JDOMException
    {
        Document dom = parse(response);
        Element root = dom.getRootElement();
        Element item = root.getChild("Items", root.getNamespace()).getChild("Item", root.getNamespace());
        Product product = new Product(item);
        Map contextMap = MacroUtils.defaultVelocityContext();
        contextMap.put("product", product);

        try
        {
            return VelocityUtils.getRenderedTemplateWithoutSwallowingErrors("/templates/extra/amazon/product.vm", new VelocityContext(contextMap));
        }
        catch (ResourceNotFoundException e)
        {
            return "<p><span class='error'>Error trying to draw image gallery: could not find template for amazon product</span></p>";
        }
        catch (Exception e)
        {
            log.error("Error while trying to render the amazon product details", e);
            return "<p><span class='error'>Error while trying to render the amazon product details: " + e.toString() + "</span></p>";
        }
    }

    private String toPrettyXml(HttpResponse response) throws IOException, JDOMException
    {
        Document dom = parse(response);
        XMLOutputter outputter = new XMLOutputter(Format.getPrettyFormat());
        return "<pre>" + new XmlFormatter().format(GeneralUtil.escapeXml(outputter.outputString(dom)), "xml") + "</pre>";
    }

    private Document parse(HttpResponse response) throws JDOMException, IOException
    {
        SAXBuilder parser = new SAXBuilder();
        Document dom = parser.build(response.getResponse());
        return dom;
    }

    private String makeSearchUrl(String asin)
    {
        StringBuffer urlBuf = new StringBuffer(BASE_AMAZON_URL.length() * 2);
        urlBuf.append(BASE_AMAZON_URL);
        urlBuf.append("&SubscriptionId=").append(getSubscriptionId());
        urlBuf.append("&Operation=ItemLookup&ItemId=").append(asin);
        urlBuf.append("&ResponseGroup=Medium");
        return urlBuf.toString();
    }

    private String getSubscriptionId()
    {
        return MY_AMAZON_ID;
    }

    public void setHttpRetrievalService(HttpRetrievalService httpRetrievalService)
    {
        this.httpRetrievalService = httpRetrievalService;
    }
}
