﻿/* See license.txt for terms of usage */

// ************************************************************************************************
// Schema Definition

/**
 * Root HTML Archive type.
 */
var logType = {
    "logType": {
        "id": "logType",
        "description": "HTTP Archive structure.",
        "type": "object",
        "properties": {
            "log": {
                "type": "object",
                "properties": {
                    "version": {"type": "string"},
                    "creator": {"$ref": "appType"},
                    "browser": {"$ref": "appType"},
                    "pages": {"items": {"$ref": "pageType"}},
                    "entries": {"items": {"$ref": "entryType"}}
                }
            }
        }
    }
};

/**
 * Application type (used to describe the exporter and browser apps).
 */
var appType = {
    "appType": {
        "id": "appType",
        "description": "External application",
        "type": "object",
        "properties": {
            "name" : {"type": "string"},
            "version" : {"type": "string"}
        }
    }
};

var pageType = {
    "pageType": {
        "id": "pageType",
        "description": "Exported web page",
        "properties": {
            "startedDateTime": {"type": "string"},
            "id": {"type": "string", "unique": true},
            "title": {"type": "string"}
        }
    }
};

var entryType = {
    "entryType": {
        "id": "entryType",
        "description": "Request and Response related info",
        "optional": true,
        "properties": {
            "pageref": {"type": "string"},
            "startedDateTime": {"type": "integer"},
            "time": {"type": "integer"},
            "sent": {"type": "integer"},
            "received": {"type" : "integer"},
            "request" : {"$ref": "requestType"},
            "response" : {"$ref": "responseType"},
            "cache" : {"$ref": "cacheType"},
            "timings" : {"$ref": "timingsType"}
        }
    }
};

var requestType = {
    "requestType": {
        "id": "requestType",
        "description": "Monitored request",
        "properties": {
            "method": {"type": "string", "enum": ["GET", "POST", "PUT", "DELETE"]},
            "prePath": {"type": "string"},
            "port": {"type": "integer"},
            "path": {"type": "string"},
            "httpVersion": {"type" : "string"},
            "cookies" : {"items": {"$ref": "recordType"}},
            "headers" : {"items": {"$ref": "recordType"}},
            "queryString" : {"items": {"$ref": "recordType"}},
            "postData" : {"$ref": "postDataType"}
        }
    }
};

var recordType = {
    "recordType": {
        "id": "recordType",
        "description": "Helper name-value pair structure.",
        "properties": {
            "name": {"type": "string"},
            "value": {"type": "string"}
        }
    }
};

var responseType = {
    "responseType": {
        "id": "responseType",
        "description": "Monitored Response.",
        "properties": {
            "status": {"type": "integer"},
            "statusText": {"type": "string"},
            "httpVersion": {"type": "string"},
            "cookies" : {"items": {"$ref": "recordType"}},
            "headers" : {"items": {"$ref": "recordType"}},
            "content" : {"$ref": "contentType"}
        }
    }
};

var postDataType = {
    "postDataType": {
        "id": "postDataType",
        "description": "Posted data info.",
        "properties": {
            "mimeType": {"type": "string"},
            "text": {"type": "string"},
            "params": {"type": "object"}
        }
    }
};

var contentType = {
    "contentType": {
        "id": "contentType",
        "description": "Response content",
        "properties": {
            "contentLength": {"type": "integer"},
            "compression": {"type": "integer"},
            "mimeType": {"type": "string"},
            "encodingScheme": {"type": "string"},
            "text": {"type": "string"}
        }
    }
};

var cacheType = {
    "cacheType": {
        "id": "cacheType",
        "description": "Info about a response coming from the cache.",
        "properties": {
            "beforeRequest": {"$ref": "cacheEntryType"},
            "afterRequest": {"$ref": "cacheEntryType"}
        }
    }
};

var cacheEntryType = {
    "cacheEntryType": {
        "id": "cacheEntryType",
        "optional": true,
        "description": "Info about associated browser cache entry.",
        "properties": {
            "expires": {"type": "string"},
            "lastModification": {"type": "string"},
            "lastAccess": {"type": "string"},
            "eTag": {"type": "string"},
            "hitCount": {"type": "integer"}
        }
    }
};

var timingsType = {
    "timingsType": {
        "id": "timingsType",
        "description": "Info about request-response timing.",
        "properties": {
            "dns": {"type": "integer"},
            "connect": {"type": "integer"},
            "blocked": {"type": "integer"},
            "send": {"type": "integer"},
            "wait": {"type": "integer"},
            "receive": {"type": "integer"},
            "DOMContentLoad": {"type": "integer"},
            "load": {"type": "integer"}
        }
    }
};

// ************************************************************************************************
// Helper schema object

function Schema() {}
Schema.prototype =
{
    registerType: function()
    {
        var doIt = function(my, obj){
            for (name in obj) {
                if (obj.hasOwnProperty(name) && name != 'prototype') {
                    my[name] = obj[name];
                }
            }
        }
        var that = this;
        for(i=0; i < arguments.length; i +=1) {
            doIt(that, arguments[i]);
        };
    }
};

// ************************************************************************************************
// Registration

// Register all defined types into the final schema object.
var schema = new Schema();
schema.registerType(
    logType,
    appType,
    pageType,
    entryType,
    requestType,
    recordType,
    responseType,
    postDataType,
    contentType,
    cacheType,
    cacheEntryType,
    timingsType
);
