//
// Change chemical/x-gaussian-log to select file for viewing.  HSR.
//
//
// PRESENTATION FUNCTIONS
//

function format_quality(mimetype) {
    var formats = {
        "chemical/x-gaussian-log" : 3,
        "chemical/x-gaussian-checkpoint" : 1,
        "chemical/x-cml" : 2,
        "chemical/x-pdb" : 2,
        "chemical/x-xyz" : 2,
        "chemical/x-mdl-molfile" : 2
    };
    return formats[mimetype] || 0;
}

function readable_format(mimetype) {
    var formats = [
        "chemical/x-gaussian-log",
        "chemical/x-gaussian-checkpoint",
        "chemical/x-cml",
        "chemical/x-pdb",
        "chemical/x-xyz",
        "chemical/x-mdl-molfile"
    ];
    var number_of_formats = formats.length;
    for(var i=0; i<number_of_formats; i++) {
        if (formats[i] === mimetype) return true;
    }
    return false;
}

function smart_selection(results) {
	var best_href;
	var best_quality = 0;
	for (var i = 0; i<results.length; i++) {
		var quality = format_quality(results[i].mimetype);
		if (quality > best_quality) {
			best_quality = quality;
			best_href = results[i].href;
		}
	}
	return best_href;
}

function present_results(results) {
    var list = document.createElement("ol");
    var list_item;
    for (var i=0; i<results.length; i++) {
        list_item = document.createElement("li");
        list_item.innerHTML = "<table><tr><th>Type:</th><td>"+results[i].mimetype+"</td></tr><tr><th>Filename:</th><td>"+results[i].filename+"</td></tr><tr><th>Location:</th><td>"+results[i].href+"</td></tr></table>";
        list.appendChild(list_item);
    }
    document.getElementById("content").innerHTML = "<p>Files:</p>";
    document.getElementById("content").appendChild(list);
}

function present_results_jmol(results, applet, handle) {
    var list = document.createElement("ol");
    var list_item;
    for (var i=0; i<results.length; i++) {
        list_item = document.createElement("li");
//         if (readable_format(results[i].mimetype)) {
//             list_item.innerHTML = "<a href='javascript:Jmol.loadFile("+applet._id+",&#39;"+results[i].href+"&#39;);'>"+results[i].filename+"</a>";
//         } else {
//             list_item.innerHTML = results[i].filename;
//         }
        list_item.innerHTML = "<a href='javascript:Jmol.loadFile("+applet._id+",&#39;"+results[i].href+"&#39;);'>"+results[i].filename+"</a>";
        list.appendChild(list_item);
    }
    applet._infoHeader = "DOI:"+handle;
    Jmol.setInfo(applet, list, true);
    console.log(applet);
}

//
// UTILITY FUNCTIONS
//

function nsResolver(prefix) {
    var ns = {
        "datacite" : "http://datacite.org/schema/kernel-3",
        "atom" : "http://www.w3.org/2005/Atom",
        "mets" : "http://www.loc.gov/METS/",
        "xlink" : "http://www.w3.org/TR/xlink/"
    };
    return ns[prefix] || "*";
}

function getElementsByTagNameNSWithAttribute(xml,ns,element,attribute,value) {
    var matchingElements = [];
    var elements = xml.getElementsByTagNameNS(ns, element);
    for (var i = 0, n = elements.length; i < n; i++) {
        if (elements[i].getAttribute(attribute) === value) {
            // Element exists with attribute. Add to array.
            matchingElements.push(elements[i]);
        }
    }
    return matchingElements;
}

//
// ASYNCHRONOUS HTTP REQUESTS AND XML PROCESSING
//

function handle_request_metadata(handle, selector, callback) {
    var httpRequest = new XMLHttpRequest();

    // REQUEST HANDLERS

    function datacite_metadata_handler() {
        if (this.readyState !== 4) return;
        if (this.status === 200) {
            // console.log(this.responseText);

            var datacite_metadata = this.responseXML;

            var metadata;
            if (metadata = datacite_metadata.querySelector("relatedIdentifier[relatedMetadataScheme='ORE']").textContent) {
                this.onreadystatechange = ore_metadata_handler;
                this.open("GET", metadata, true);
                this.send(null);
            } else if (metadata = datacite_metadata.querySelector("relatedIdentifier[@relatedMetadataScheme='METS']").textContent) {
                this.onreadystatechange = mets_metadata_handler;
                this.open("GET", metadata, true);
                this.send(null);
            } else {
                alert("Could not find ORE or METS metadata");
            }
            console.log(metadata);
        }
        else {
                alert("DOI metadata unavailable. See  https://status.datacite.org for details");
        }
    }

    function mets_metadata_handler() {
        if (this.readyState !== 4) return;
        if (this.status === 200) {
            if (selector) {
                handle_resolve_s_mets(this.responseXML);
            } else {
                handle_resolve_mets(this.responseXML);
            }
        } else alert('No METS metadata');
    }

    function ore_metadata_handler() {
        if (this.readyState !== 4) return;
        if (this.status === 200) {
            if (selector) {
                handle_resolve_s_ore(this.responseXML);
            } else {
                handle_resolve_ore(this.responseXML);
            }
        } else alert('No ORE metadata');
    }

    // XML PROCESSING

    function handle_resolve_mets(mets) {
        var files = mets.getElementsByTagNameNS(nsResolver("mets"), "file");
        var results = [];
        for (var j = 0, n = files.length; j<n; j++ ) {
            var mimetype = files[j].getAttribute("MIMETYPE");
            var filename = files[j].getElementsByTagNameNS(nsResolver("mets"), "FLocat").getAttributeNS(nsResolver("xlink"), "title");
            var href = files[j].getElementsByTagNameNS(nsResolver("mets"), "FLocat").getAttributeNS(nsResolver("xlink"), "href");
            var result = new Object();
            result.mimetype = mimetype;
            result.filename = filename;
            result.href = href;
            console.log(result);
            results.push(result);
        }
        callback(results);
    }

    function handle_resolve_ore(ore) {
        var files = getElementsByTagNameNSWithAttribute(ore, nsResolver("atom"), "link", "rel", "http://www.openarchives.org/ore/terms/aggregates");
        var results = [];
        for (var j = 0, n = files.length; j<n; j++ ) {
            var mimetype = files[j].getAttribute("type");
            var filename = files[j].getAttribute("title");
            var href = files[j].getAttribute("href");
            var result = new Object();
            result.mimetype = mimetype;
            result.filename = filename;
            result.href = href;
            console.log(result);
            results.push(result);
        }
        callback(results);
    }

    function handle_resolve_s_mets(mets) {
        var href;
        var files = mets.getElementsByTagNameNS(nsResolver("mets"), "file");
        for (var i = 0, n = files.length; i<n; i++) {
            if (files[i].getAttribute("MIMETYPE") === selector || files[i].getElementsByTagNameNS(nsResolver("mets"), "FLocat").getAttributeNS(nsResolver("xlink"), "title") === selector) {
                href = files[i].getElementsByTagNameNS(nsResolver("mets"), "FLocat").getAttributeNS(nsResolver("xlink"), "href");
            }
        }
        callback(href);
    }

    function handle_resolve_s_ore(ore) {
        var href;
        var files = getElementsByTagNameNSWithAttribute(ore, nsResolver("atom"), "link", "rel", "http://www.openarchives.org/ore/terms/aggregates");
        for (var i = 0, n = files.length; i<n; i++) {
            if (files[i].getAttribute("type") === selector || files[i].getAttribute("title") === selector) {
                href = files[i].getAttribute("href");
            }
        }
        callback(href);
    }

    httpRequest.onreadystatechange = datacite_metadata_handler;
    httpRequest.open("GET", "https://api.datacite.org/dois/" + handle, true);
    httpRequest.setRequestHeader("Accept", "application/vnd.datacite.datacite+xml");
    httpRequest.send(null);
}

//
// API FUNCTIONS
//

function handle_do() {
    var handle = document.getElementById("handleid").value;
    var selector = document.getElementById("handleselector").value || "logfile.log";
    // request metadata with callback function
    handle_request_metadata(handle, selector, function(href) {
        console.log(href);
        document.getElementById("content").innerHTML = "<p>"+href+"</p>";
    });
}

//
// Change chemical/x-gaussian-log to select file for viewing.  HSR.
//
function handle_jmol(query, jmol_script, applet) {
    if (applet === undefined) applet = jmolApplet0;
    query = query.split("?");
    var handle = query[0];
    var selector = query[1] || "chemical/x-gaussian-log";
    // request metadata with callback function to send result at jmol.
    handle_request_metadata(handle, selector, function(href) {
        Jmol.loadFile(applet, href, jmol_script);
        Jmol.script(applet, 'set echo TOP LEFT;font echo 12; echo "doi:'+handle+' '+selector+'";');
    });
}

function handle_jmol_demo() {
    var handle = document.getElementById("handleid").value;
    var selector = document.getElementById("handleselector").value;
    var smart = document.getElementById("handlesmart").checked;
    var applet = jmolApplet0;
    if (selector) {
        handle_request_metadata(handle, selector, function(href) {
            console.log(href);
            document.getElementById("content").innerHTML = "<p>"+href+"</p>";
            if (href) {
                Jmol.loadFile(applet, href);
            }
        });
    } else if (smart) {
        handle_request_metadata(handle, null, function(results) {
            console.log(results);
            var href;
            if (href = smart_selection(results)) {
                console.log(href);
                Jmol.loadFile(applet, href);
            } else {
                present_results_jmol(results, applet, handle);
            }
        });
    } else {
        handle_request_metadata(handle, null, function(results) {
            console.log(results);
            present_results_jmol(results, applet, handle);
        });
    }
}
