/*jslint fudge, long, for*/
"use strict";

// Notes:  using JSLint.com and JSHint.com
//         Changed == and != to === and !== for ESLint
//         Consider Google Closure Compiler

// PSK NameSpace's
//var pskNs = "http://schemas.microsoft.com/windows/2003/08/printing/printschemakeywords";
//var psk11Ns = "http://schemas.microsoft.com/windows/2013/05/printing/printschemakeywordsv11";
//var psk12Ns = "http://schemas.microsoft.com/windows/2013/12/printing/printschemakeywordsv12";

//// psf NameSpace's
//var psf2Ns = "http://schemas.microsoft.com/windows/2013/12/printing/printschemaframework2";
var psfNs = "http://schemas.microsoft.com/windows/2003/08/printing/printschemaframework";

// XML Schema NameSpace's
var xsiNs = "http://www.w3.org/2001/XMLSchema-instance";
//var xsdNs = "http://www.w3.org/2001/XMLSchema";

// KIP driver NameSpace
var ns0000Ns = "http://www.kipamerica.com/Schema";

var MaxParamenterCount = 100;


function setStandardNameSpaces(xmlNode) {
    /// <summary>
    /// Set the Selection namespace values to below namesapces
    /// xmlns:psf='http://schemas.microsoft.com/windows/2003/08/printing/printschemaframework'
    /// xmlns:psf2='http://schemas.microsoft.com/windows/2013/12/printing/printschemaframework2'
    /// xmlns:psk='http://schemas.microsoft.com/windows/2003/08/printing/printschemakeywords'
    /// xmlns:psk11='http://schemas.microsoft.com/windows/2013/05/printing/printschemakeywordsv11'
    /// xmlns:psk12='http://schemas.microsoft.com/windows/2013/12/printing/printschemakeywordsv12'
    /// xmlns:xsd='http://www.w3.org/2001/XMLSchema'
    /// xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
    /// xmlns:ns0000= http://www.kipamerica.com/Schema'
    ///</summary>
    /// <param name="node" type="IXMLDOMNode">
    ///     A node in the XML document.
    /// </param>

    xmlNode.setProperty(
        "SelectionNamespaces",
        "xmlns:psf='http://schemas.microsoft.com/windows/2003/08/printing/printschemaframework' "
        + "xmlns:psf2='http://schemas.microsoft.com/windows/2013/12/printing/printschemaframework2' "
        + "xmlns:psk='http://schemas.microsoft.com/windows/2003/08/printing/printschemakeywords' "
        + "xmlns:psk11='http://schemas.microsoft.com/windows/2013/05/printing/printschemakeywordsv11' "
        + "xmlns:psk12='http://schemas.microsoft.com/windows/2013/12/printing/printschemakeywordsv12' "
        + "xmlns:xsd='http://www.w3.org/2001/XMLSchema' "
        + "xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' "
        + "xmlns:ns0000='http://www.kipamerica.com/Schema' "
    );
    return;
}

// Used here to check that print ticket has namespace defined, validating that PrintTicket is for our driver
function getPrefixForNamespace(node, namespace) {
    /// <summary>
    ///     This function returns the prefix for a given namespace.
    ///     Example: In 'psf:printTicket', 'psf' is the prefix for the namespace.
    ///     xmlns:psf="http://schemas.microsoft.com/windows/2003/08/printing/printschemaframework"
    /// </summary>
    /// <param name="node" type="IXMLDOMNode">
    ///     A node in the XML document.
    /// </param>
    /// <param name="namespace" type="String">
    ///     The namespace for which prefix is returned.
    /// </param>
    /// <returns type="String">
    ///     Returns the namespace corresponding to the prefix.
    /// </returns>

    if (!node) {
        return null;
    }

    // Navigate to the root element of the document.
    var rootNode = node.documentElement;

    // Query to retrieve the list of attribute nodes for the current node
    // that matches the namespace in the 'namespace' variable.
    var xPathQuery = "namespace::node()[.='"
        + namespace
        + "']";
    var namespaceNode = rootNode.selectSingleNode(xPathQuery);

    var prefix;
    if (namespaceNode !== null) {
        prefix = namespaceNode.baseName;
    }

    return prefix;
}

function createProperty(strPropertyName, strNodeName, strValueType, strValue, documentNode) {
    /// <summary>
    /// Create a property XML Node with child Value Node containing the value
    /// </summary>
    /// <param name="strPropertyName" type="String">
    ///   Name of the property Node
    /// </param>
    /// <param name="strNodeName" type="String">
    ///   Name to be assigned to the "name" attribute of the property
    /// </param>
    /// <param name="strValueType" type="String">
    ///   Type of the value the in the Value Node
    /// </param>
    /// <param name="strValue" type="String">
    ///   Actual value that is to be placed in the value node
    /// </param>
    /// <param name="documentNode" type="IXMLNode">
    ///   Contains Document XML Node
    /// </param>

    var newNode = documentNode.XmlNode.createNode(1, strNodeName, psfNs);
    newNode.setAttribute("name", strPropertyName);

    if (strValueType.length > 0) {
        var newProp = documentNode.XmlNode.createNode(1, "psf:Value", psfNs);
        var newAttr = documentNode.XmlNode.createNode(2, "xsi:type", xsiNs);
        newAttr.nodeValue = strValueType;
        newProp.setAttributeNode(newAttr);

        var newText = documentNode.XmlNode.createTextNode(strValue);

        newProp.appendChild(newText);

        newNode.appendChild(newProp);
    }
    return newNode;
}



//function getDevModeProperties(devModeProperties) {
//    /// <summary>
//    ///   Get the base names for the ParameterDefs defined in the devmode map file
//    /// </summary>
//    /// <param name="devModeProperties" type="IPrinterScriptablePropertyBag">
//    ///     The DevMode property bag.
//    /// </param>

//    // our list of devmode properties

//    //// Get devModeMap
//    var devModeMap = devModeProperties.GetReadStreamAsXML("Properties");  // causes failure

//}





function completePrintCapabilities(printTicket, scriptContext, printCapabilities) {
    /// <param name="printTicket" type="IPrintSchemaTicket" mayBeNull="true">
    ///     If not 'null', the print ticket's settings are used to customize the print capabilities.
    /// </param>
    /// <param name="scriptContext" type="IPrinterScriptContext">
    ///     Script context object.
    /// </param>
    /// <param name="printCapabilities" type="IPrintSchemaCapabilities">
    ///     Print capabilities object to be customized.
    /// </param>

    return;
}


/* Custom paramenter data is stored in the devmode.
 * The print systems uses functions below to move the data into the print ticket,
 * before opening UI or sending to print.
 * And to move the data back into devmode after UI.
 * So all our custom paramenters must be defined in the devmode map.
 * PrintTicket parameters are only of type string, no integers etc.
 */



function transferDm2PtString(stringName, printTicket, devModeProperties) {
    /// <summary>
    ///     Transfer a devmode mapped property to the print ticket
    ///     Returns true, unless the imput stringName is not in the devmode map
    /// </summary>
    /// <param name="stringName" type="string>
    ///     Name of property in the devmode map
    /// </param>
    /// <param name="devModeProperties" type="IPrinterScriptablePropertyBag">
    /// <param name="printTicket" type="IPrintSchemaTicket">
    ///     Print ticket to be converted from the DevMode.
    /// </param>
    ///     The DevMode property bag.
    /// </param>

    if (stringName === null) {
        return false;
    }

    try {
        // causes failure if unsucesful, so we put in try block
        var paramString = devModeProperties.getString(stringName);

        // If Devmode string is present, map to print ticket either by creating a new node or modifying the existing node
        if (paramString !== null) {

            // Try getting the related ParameterInit in the PrintTicket
            var currNode = printTicket.GetParameterInitializer(stringName, ns0000Ns);

            if (currNode === null) {
                // Create node if no node is present

                // Add prefix to ParameterDef base name
                var paramName = "ns0000:" + stringName;

                var newParam = createProperty(paramName, "psf:ParameterInit", "xsd:string", paramString, printTicket);
                var ptRoot = printTicket.XmlNode.selectSingleNode("psf:PrintTicket");
                ptRoot.appendChild(newParam);
            }
            else {
                // Change the value of the node to Devmode string value
                currNode.Value = paramString;
            }
            return true;
        }
    }
    catch (error) {
        return false;
    }
    return false;
}

function convertDevModeToPrintTicket(devModeProperties, scriptContext, printTicket) {
    /// <param name="devModeProperties" type="IPrinterScriptablePropertyBag">
    ///     The DevMode property bag.
    /// </param>
    /// <param name="scriptContext" type="IPrinterScriptContext">
    ///     Script context object.
    /// </param>
    /// <param name="printTicket" type="IPrintSchemaTicket">
    ///     Print ticket to be converted from the DevMode.
    /// </param>

    // Set Standard namespaces with prefixes
    setStandardNameSpaces(printTicket.XmlNode);

    // Get prefix for our namespace
    // If namespace prefix is not found, that means that print ticket is produced by a different printer and there is not our name space within print ticket.
    // This could happen with some legacy application using print ticket wrongly. To avoid failures we are checking first and shot circuiting the rest of the code.

    var ns0000NsPrefix = getPrefixForNamespace(printTicket.XmlNode, ns0000Ns);
    if (ns0000NsPrefix !== null) {

        // Can add others like this
        //transferDm2PtString("K1", printTicket, devModeProperties);

        var propBaseName = "JobData";
        var name;
        var num = 0;

        // try up to limit
        for (num = 1; num < MaxParamenterCount; num += 1) {
            name = propBaseName + num.toString();
            if (transferDm2PtString(name, printTicket, devModeProperties) === false) {
                break;
            }
        }
    }
    return;
}

function transferPt2DmString(stringName, printTicket, devModeProperties) {
    /// <summary>
    ///   Transfer a devmode mapped property from the print ticket to the devmode property
    ///   Returns true, unless the imput stringName is not in the devmode map
    /// </summary>
    /// <param name="stringName" type="string>
    ///     Name of property in the devmode map
    /// </param>
    /// <param name="devModeProperties" type="IPrinterScriptablePropertyBag">
    /// <param name="printTicket" type="IPrintSchemaTicket">
    ///     Print ticket to be converted from the DevMode.
    /// </param>
    ///     The DevMode property bag.
    /// </param>

    try {
        // Try getting the related ParameterInit in the PrintTicket
        var currNode = printTicket.GetParameterInitializer(stringName, ns0000Ns);
        if (currNode !== null) {
            devModeProperties.setString(stringName, currNode.Value);
            return true;
        }
    }
    catch (error) { // ususally because stringName is not in devmode map
    }
    return false;
}



function convertPrintTicketToDevMode(printTicket, scriptContext, devModeProperties) {
    /// <param name="printTicket" type="IPrintSchemaTicket">
    ///     Print ticket to be converted to DevMode.
    /// </param>
    /// <param name="scriptContext" type="IPrinterScriptContext">
    ///     Script context object.
    /// </param>
    /// <param name="devModeProperties" type="IPrinterScriptablePropertyBag">
    ///     The DevMode property bag.
    /// </param>

    // Set Standard namespaces with prefixes
    setStandardNameSpaces(printTicket.XmlNode);

    // Get prefix for our namespace
    // If namespace prefix is not found, that means that print ticket is produced by a different printer and there is not PDF name space with in print ticket
    // This could happen with some legacy application using print ticket wrongly. To avoid failures we are checking first and short circuiting the rest of the code.

    var ns0000NsPrefix = getPrefixForNamespace(printTicket.XmlNode, ns0000Ns);
    if (ns0000NsPrefix !== null) {

        // Can add others like this:
        //transferPt2DmString("K1", printTicket, devModeProperties);

        var propBaseName = "JobData";
        var name;
        var num = 0;

        // try up to limit
        for (num = 1; num < MaxParamenterCount; num += 1) {
            name = propBaseName + num.toString();
            if (transferPt2DmString(name, printTicket, devModeProperties) === false) {
                break;
            }
        }
    }
    return;
}

function validatePrintTicket(printTicket, scriptContext) {
    /// <param name="printTicket" type="IPrintSchemaTicket">
    ///     Print ticket to be validated.
    /// </param>
    /// <param name="scriptContext" type="IPrinterScriptContext">
    ///     Script context object.
    /// </param>
    /// <returns type="Number" integer="true">
    ///     Integer value indicating validation status.
    ///         1 - Print ticket is valid and was not modified.
    ///         2 - Print ticket was modified to make it valid.
    ///         0 - Print ticket is invalid.
    /// </returns>

    // There is nothing wrong with having only 1, 2 or 3 ParameterInit’s in PrintTicket for the same ParameterDefs that are present in PDC.
    // For that reason we just going to return 1 without any check
    return 1;
}

