package dendrarium.portal.answer;

import dendrarium.trees.svg.SVGImage;
import dendrarium.core.entities.User;
import dendrarium.trees.Forest;
import dendrarium.trees.Node;
import dendrarium.trees.NonterminalNode;
import dendrarium.trees.disamb.ChildInfo;
import dendrarium.trees.disamb.Variant;
import dendrarium.trees.svg.NodeTreeDrawer;
import dendrarium.trees.svg.TreeDrawer;
import dendrarium.trees.json.TreeOutputter;
import java.io.IOException;
import java.io.Serializable;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.Import;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Logger;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Out;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.core.Manager;
import org.jboss.seam.document.DocumentData;
import org.jboss.seam.document.DocumentStore;
import org.jboss.seam.log.Log;
import org.jdom.Element;
import org.jdom.output.XMLOutputter;
import org.json.JSONObject;
import org.json.JSONException;

/**
 *
 * @author Piotr Achinger <piotr.achinger at gmail.com>
 */
@Name("treeRenderer")
@Scope(ScopeType.CONVERSATION)
@Import("org.jboss.seam.document")
public class TreeRenderer implements Serializable {

    @In
    User user;

    @In
    Manager manager;

    @Logger
    Log log;

    @Out(required = false)
    String currentImageURL;

    @Out(required = false)
    String currentImageData;

    @Out(required = false)
    Integer currentImagePosX;

    @Out(required = false)
    Integer currentImagePosY;

    @Out(required = false)
    String currentTreeInfo;

    @Out(required = false)
    String fullTreeInfo;

    @Out(required = false)
    String fullTreeURL;

    private final double toPx = 37.9 / 120.0;

    Map<Integer, SVGImage> images = new HashMap<Integer, SVGImage>();

    private String redirectUrl(String url) {
        return manager.encodeConversationId(url, manager.getCurrentConversationViewId());
    }

    public void remove(SVGImage image) {
        /* nop */
    }

    public JSONObject generateTreeInfo(Forest forest, Node node,
            List<NonterminalNode> accessibleNodes, boolean strip) {
        Map<Integer, Integer> links = new HashMap();
        int i = 0;
        if (accessibleNodes != null)
            for (NonterminalNode n : accessibleNodes)
                links.put(n.getId(), i ++);

        try {
            JSONObject obj = TreeOutputter.forestToJSON(forest,
                    node, links, strip, false);

            currentTreeInfo = obj.toString();

            if (!strip) {
                JSONObject full = TreeOutputter.forestToJSON(forest,
                        node, links, strip, true);

                fullTreeInfo = full.toString();
                fullTreeURL = postJSON(full);
            }

            return obj;
        } catch (JSONException ex) {
            currentTreeInfo = "{ \"error\": \"" + ex.toString() + "\" }";
            return null;
        }
    }

    public SVGImage renderImage(Forest forest, Node node,
            List<NonterminalNode> accessibleNodes) {
        Map<Integer, String> links = new HashMap();
        if (accessibleNodes != null)
        {
        for (int i = 0 ; i < accessibleNodes.size() ; ++i) {
            Node n = accessibleNodes.get(i);

            String buttonId = "main:accessibleNodes:" + i + ":nodebutton";
            String action = "javascript:document.getElementById('" + buttonId + "').click()";

            links.put(n.getId(), action);
        }
        }

//        byte[] data = XMLUtils.writePrettyByteArrayJDOM(
        TreeDrawer td = new TreeDrawer();
        Element svg = td.drawInteractiveSVGTree(forest, node, links);
        int X = td.getPosX();
        int Y = td.getPosY();

//                SVGJdom.getStandardDocType()));
        XMLOutputter xmlOut = new XMLOutputter();
        StringWriter writer = new StringWriter();
        try {
            xmlOut.output(svg, writer);
        } catch (IOException ex) {
            java.util.logging.Logger.getLogger(TreeRenderer.class.getName()).log(Level.SEVERE, null, ex);
        }
        String outString = writer.toString();
        byte[] data = outString.getBytes();

        SVGImage image = postImage(data, "tree");
        image.setPosX(X);
        image.setPosY(Y);

        currentImageURL = image.getImageUrl();
        currentImageData = new String(image.getData());
        currentImagePosX = new Double(image.getPosX() * toPx).intValue();
        currentImagePosY = new Double(image.getPosY() * toPx).intValue();

        return image;
    }

    public void renderVariants(int hash, List<Variant> variants) {
        /* generacja malych drzewek */
        int i = 0;
        for (Variant variant : variants) {
            SVGImage nimage = renderNodeImage(variant);

            variant.setImage(nimage);

            images.put(hash + 2137 * i + 1771, nimage);
            ++i;
        }
    }

    public SVGImage renderNodeImage(Variant variant) {
        String rule = variant.getRule();
        List<ChildInfo> childList = variant.getChildren();

        byte[] data = new NodeTreeDrawer().getSVGTree(rule, childList);

        return postImage(data, "subtree");
    }

    public SVGImage postImage(byte[] data, String name) {
        DocumentStore documentStore = DocumentStore.instance();

        DocumentData dd = new DocumentData(name, new DocumentData.DocumentType("svg", "image/svg+xml"), data);

        dd.setDisposition("inline");

        String id = documentStore.newId();

        documentStore.saveData(id, dd);

        String documentUrl =
               documentStore.preferredUrlForContent(
                dd.getBaseName(),
                dd.getDocumentType().getExtension(),
                id);

        log.info("RENDERED IMAGE " + documentUrl + " : " + dd.getBaseName() + " : " + id);

        String url = redirectUrl(documentUrl);

        return new SVGImage(data, id, url);
    }

    public String postJSON(JSONObject js) {
        DocumentStore documentStore = DocumentStore.instance();
        DocumentData dd = new DocumentData("json",
                        new DocumentData.DocumentType("js", "text/javascript"),
                        ("helper_load(" + js.toString() + ");").getBytes());

        dd.setDisposition("inline");

        String id = documentStore.newId();
        documentStore.saveData(id, dd);

        String documentUrl =
               documentStore.preferredUrlForContent(
                dd.getBaseName(),
                dd.getDocumentType().getExtension(),
                id);

        log.info("JSON " + documentUrl + " : " + dd.getBaseName() + " : " + id);

        return redirectUrl(documentUrl);
    }
}
