/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

/* {
    oldname:'odata.js',
    updated:'20140514 12:59'
}*/

// odata.js

// Imports
var odataUtils    = exports.utils     = require('./odata/utils.js');
var odataHandler  = exports.handler   = require('./odata/handler.js');
var odataMetadata = exports.metadata  = require('./odata/metadata.js');
var odataNet      = exports.net       = require('./odata/net.js');
                    exports.gml       = require('./odata/gml.js');
var odataJson     = exports.json      = require('./odata/json.js');
var odataAtom     = exports.atom      = require('./odata/atom.js');
var odataXml      = exports.xml       = require('./odata/xml.js');
                    exports.batch     = require('./odata/batch.js');
                    
exports.metadataHandler =  odataMetadata.metadataHandler;





var utils = require('./datajs/utils.js');
var assigned = utils.assigned;

var assigned = utils.assigned;
var defined = utils.defined;
var throwErrorCallback = utils.throwErrorCallback;

var invokeRequest = odataUtils.invokeRequest;
var MAX_DATA_SERVICE_VERSION = odataHandler.MAX_DATA_SERVICE_VERSION;
var prepareRequest = odataUtils.prepareRequest;
var metadataParser = odataMetadata.metadataParser;

// CONTENT START

// to do: disable atom scenario
var handlers = [odataJson.jsonHandler/*, odata.atomHandler*/, odataXml.xmlHandler, odataHandler.textHandler];

var dispatchHandler = function (handlerMethod, requestOrResponse, context) {
    /// <summary>Dispatches an operation to handlers.</summary>
    /// <param name="handlerMethod" type="String">Name of handler method to invoke.</param>
    /// <param name="requestOrResponse" type="Object">request/response argument for delegated call.</param>
    /// <param name="context" type="Object">context argument for delegated call.</param>

    var i, len;
    for (i = 0, len = handlers.length; i < len && !handlers[i][handlerMethod](requestOrResponse, context); i++) {
    }

    if (i === len) {
        throw { message: "no handler for data" };
    }
};

exports.defaultSuccess = function (data) {
    /// <summary>Default success handler for OData.</summary>
    /// <param name="data">Data to process.</param>

    window.alert(window.JSON.stringify(data));
};

exports.defaultError = throwErrorCallback;

exports.defaultHandler = {
        read: function (response, context) {
            /// <summary>Reads the body of the specified response by delegating to JSON and ATOM handlers.</summary>
            /// <param name="response">Response object.</param>
            /// <param name="context">Operation context.</param>

            if (response && assigned(response.body) && response.headers["Content-Type"]) {
                dispatchHandler("read", response, context);
            }
        },

        write: function (request, context) {
            /// <summary>Write the body of the specified request by delegating to JSON and ATOM handlers.</summary>
            /// <param name="request">Reques tobject.</param>
            /// <param name="context">Operation context.</param>

            dispatchHandler("write", request, context);
        },

        maxDataServiceVersion: MAX_DATA_SERVICE_VERSION,
        accept: "application/json;q=0.9, application/atomsvc+xml;q=0.8, */*;q=0.1"
    };

exports.defaultMetadata = []; //TODO check why is the defaultMetadata an Array? and not an Object.

exports.read = function (urlOrRequest, success, error, handler, httpClient, metadata) {
    /// <summary>Reads data from the specified URL.</summary>
    /// <param name="urlOrRequest">URL to read data from.</param>
    /// <param name="success" type="Function" optional="true">Callback for a successful read operation.</param>
    /// <param name="error" type="Function" optional="true">Callback for handling errors.</param>
    /// <param name="handler" type="Object" optional="true">Handler for data serialization.</param>
    /// <param name="httpClient" type="Object" optional="true">HTTP client layer.</param>
    /// <param name="metadata" type="Object" optional="true">Conceptual metadata for this request.</param>

    var request;
    if (urlOrRequest instanceof String || typeof urlOrRequest === "string") {
        request = { requestUri: urlOrRequest };
    } else {
        request = urlOrRequest;
    }

    return exports.request(request, success, error, handler, httpClient, metadata);
};

exports.request = function (request, success, error, handler, httpClient, metadata) {
    /// <summary>Sends a request containing OData payload to a server.</summary>
    /// <param name="request" type="Object">Object that represents the request to be sent.</param>
    /// <param name="success" type="Function" optional="true">Callback for a successful read operation.</param>
    /// <param name="error" type="Function" optional="true">Callback for handling errors.</param>
    /// <param name="handler" type="Object" optional="true">Handler for data serialization.</param>
    /// <param name="httpClient" type="Object" optional="true">HTTP client layer.</param>
    /// <param name="metadata" type="Object" optional="true">Conceptual metadata for this request.</param>

    success = success || exports.defaultSuccess;
    error = error || exports.defaultError;
    handler = handler || exports.defaultHandler;
    httpClient = httpClient || odataNet.defaultHttpClient;
    metadata = metadata || exports.defaultMetadata;

    // Augment the request with additional defaults.
    request.recognizeDates = utils.defined(request.recognizeDates, odataJson.jsonHandler.recognizeDates);
    request.extendMetadataToLevel = utils.defined(request.extendMetadataToLevel, odataJson.jsonHandler.extendMetadataToLevel);
    request.callbackParameterName = utils.defined(request.callbackParameterName, odataNet.defaultHttpClient.callbackParameterName);
    request.formatQueryString = utils.defined(request.formatQueryString, odataNet.defaultHttpClient.formatQueryString);
    request.enableJsonpCallback = utils.defined(request.enableJsonpCallback, odataNet.defaultHttpClient.enableJsonpCallback);

    // Create the base context for read/write operations, also specifying complete settings.
    var context = {
        metadata: metadata,
        recognizeDates: request.recognizeDates,
        extendMetadataToLevel : request.extendMetadataToLevel,
        callbackParameterName: request.callbackParameterName,
        formatQueryString: request.formatQueryString,
        enableJsonpCallback: request.enableJsonpCallback,
    };

    try {
        odataUtils.prepareRequest(request, handler, context);
        return odataUtils.invokeRequest(request, success, error, handler, httpClient, context);
    } catch (err) {
        // errors in success handler for sync requests are catched here and result in error handler calls. 
        // So here we fix this and throw that error further.
        if (err.bIsSuccessHandlerError) {
            throw err;
        } else {
            error(err);
        }
    }

};

exports.parseMetadata = function (csdlMetadataDocument) {
    /// <summary>Parses the csdl metadata to DataJS metatdata format. This method can be used when the metadata is retrieved using something other than DataJS</summary>
    /// <param name="atomMetadata" type="string">A string that represents the entire csdl metadata.</param>
    /// <returns type="Object">An object that has the representation of the metadata in Datajs format.</returns>

    return metadataParser(null, csdlMetadataDocument);
};

// Configure the batch handler to use the default handler for the batch parts.
exports.batch.batchHandler.partHandler = exports.defaultHandler;
