/*
 * Copyright (C) 2005 - 2011 Jaspersoft Corporation. All rights reserved.
 * http://www.jaspersoft.com.
 *
 * Unless you have purchased  a commercial license agreement from Jaspersoft,
 * the following license terms  apply:
 *
 * This program is free software: you can redistribute it and/or  modify
 * it under the terms of the GNU Affero General Public License  as
 * published by the Free Software Foundation, either version 3 of  the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Affero  General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public  License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

/**
 * Asynchronous action class.
 */
repositorySearch.Action = function(invokeFn) {
    if (Object.isFunction(invokeFn)) {
        this.invokeAction = invokeFn;
    }
};
repositorySearch.Action.addMethod('invokeAction', doNothing);

repositorySearch.folderActionFactory = {
    "CreateFolder": function(folder) {
        return new repositorySearch.Action(function() {
            repositorySearch.showCreateFolderConfirm(folder);
        });
    },

    "CopyFolder": function(folder) {
        return new repositorySearch.Action(function() {
            repositorySearch.CopyMoveController.copy(folder);
        });
    },

    "MoveFolder": function(folder) {
        return new repositorySearch.Action(function() {
            repositorySearch.CopyMoveController.move(folder);
        });
    },

    "PasteFolder": function(folder) {
        return new repositorySearch.Action(function() {
            var actionName;
            var toFolder = folder ? folder : repositorySearch.model.getContextFolder();

            var object = repositorySearch.CopyMoveController.object;

            if (repositorySearch.CopyMoveController.isCopyFolder()) {

                actionName = repositorySearch.FolderAction.COPY;

            } else if (repositorySearch.CopyMoveController.isMoveFolder()) {

                actionName = repositorySearch.FolderAction.MOVE;

            } else {
                return;
            }

            var action = new repositorySearch.ServerAction.createFolderAction(actionName, {
                toFolder: toFolder,
                folder: repositorySearch.CopyMoveController.object
            });

            action.invokeAction();
        });
    },

    "PasteResources": function(folder) {
        return new repositorySearch.Action(function() {
            var actionName;
            var toFolder = folder ? folder : repositorySearch.model.getContextFolder();

            var object = repositorySearch.CopyMoveController.object;
            var resources = (repositorySearch.CopyMoveController.isBulkAction()) ? object : [object];

            if (repositorySearch.CopyMoveController.isCopyResource()) {

                actionName = repositorySearch.ResourceAction.COPY;

            } else if (repositorySearch.CopyMoveController.isMoveResource()) {

                actionName = repositorySearch.ResourceAction.MOVE;

            } else {
                return;
            }

            var action = new repositorySearch.ServerAction.createResourceAction(actionName, {
                resources: resources,
                folder: toFolder
            });

            action.invokeAction();
        });
    },

    "DeleteFolder": function(folder) {
        return new repositorySearch.Action(function() {
            actionModel.hideMenu();
            repositorySearch.showDeleteFolderConfirm(folder)
        });
    },

    "ShowFolderProperties": function(folder) {
        return new repositorySearch.Action(function() {
            repositorySearch.showFolderProperties(folder);
        });
    },

    "EditFolderProperties": function(folder) {
        return new repositorySearch.Action(function() {
            repositorySearch.editFolderProperties(folder);
        });
    },

    "AssignPermissions": function(folder) {
        return new repositorySearch.Action(function() {
            repositorySearch.editFolderPermissions(folder);
        });
    },

    "SetActiveThemeFolder": function(folder) {
        return new repositorySearch.Action(function() {
            var action = new repositorySearch.ServerAction.createFolderAction(
                repositorySearch.ThemeAction.SETTHEME, {folder: folder});
            action.invokeAction();
        });
    },

    "DownloadTheme": function(folder) {
        return new repositorySearch.Action(function() {
            var action = new repositorySearch.ServerAction.createFolderAction(
                repositorySearch.ThemeAction.DOWNLOAD_THEME, {folder: folder});
            action.initDownload();
        });
    },

    "UploadTheme": function(folder) {
        return new repositorySearch.Action(function() {
            repositorySearch.showUploadThemeConfirm(folder);
        });
    }
};

repositorySearch.resourceActionFactory = {
    "Copy": function(resource) {
        return new repositorySearch.Action(function() {
            repositorySearch.CopyMoveController.copy(resource);
        });
    },

    "Move": function(resource) {
        return new repositorySearch.Action(function() {
            repositorySearch.CopyMoveController.move(resource);
        });
    },

    "Delete": function(resource) {
        return new repositorySearch.Action(function() {
            actionModel.hideMenu();
            repositorySearch.showDeleteResourceConfirm(resource)
        });
    },

    "ShowProperties": function(resource, options) {
        return new repositorySearch.Action(function() {
            repositorySearch.showResourceProperties(resource, options);
        });
    },

    "EditProperties": function(resource, options) {
        return new repositorySearch.Action(function() {
            repositorySearch.editResourceProperties(resource, options);
        });
    },

    "AssignPermissionsToResourceAction":  function(resource) {
        return new repositorySearch.Action(function() {
            repositorySearch.editResourcePermissions(resource);
        });
    }
};

repositorySearch.bulkActionFactory = {
    "Run": function(resources) {
        return new repositorySearch.Action(function() {
            resources.each(function(resource, index) {
                var action = repositorySearch.RedirectAction.createRunResourceAction(resource, index != 0);
                action.invokeAction();
            });
        });
    },

    "Edit": function(resources) {
        return new repositorySearch.Action(function() {
            resources.each(function(resource, index) {
                var action = repositorySearch.RedirectAction.createEditResourceAction(resource, index != 0);
                action.invokeAction();
            });
        });
    },

    "Open": function(resources) {
        return new repositorySearch.Action(function() {
            resources.each(function(resource, index) {
                var action = repositorySearch.RedirectAction.createOpenResourceAction(resource, index != 0);
                action.invokeAction();
            });
        });
    },

    "Copy": function(resources) {
        return new repositorySearch.Action(function() {
            repositorySearch.CopyMoveController.copy(resources);
        });
    },

    "Move": function(resources) {
        return new repositorySearch.Action(function() {
            repositorySearch.CopyMoveController.move(resources);
        });
    },

    "Delete": function(resources) {
        return new repositorySearch.Action(function() {
            actionModel.hideMenu();
            repositorySearch.showBulkDeleteResourcesConfirm(resources);
        });
    },

    "ShowProperties": function(resources) {
        return new repositorySearch.Action(function() {
            resources.each(function(resource, index) {
                invokeResourceAction("ShowProperties", resource, {cascade: true, position: index, number: resources.length});
            });
        });
    },

    "EditProperties": function(resources) {
        return new repositorySearch.Action(function() {
            resources.each(function(resource, index) {
                invokeResourceAction("EditProperties", resource, {cascade: true, position: index, number: resources.length});
            });
        });
    }
};

/**
 * Server action class.
 */
repositorySearch.ServerAction = function(eventId, options) {
    this.actionURL = 'flow.html?_flowExecutionKey=' + repositorySearch.flowExecutionKey + '&_eventId=' + eventId;

    this.data = Object.toQueryString(options.data);
};

/**
 * Invokes server action.
 */
repositorySearch.ServerAction.addMethod('invokeAction', function() {
    ajaxTargettedUpdate(this.actionURL, {
        postData: this.data,
        callback: function(response) {
            if (response.status == 'OK') {
                this.onSuccess(response.data);
            } else {
                this.onError(response.data);
            }
        }.bind(this),
        errorHandler: this._serverErrorHandler,
        mode: AjaxRequester.prototype.EVAL_JSON
    });
});

repositorySearch.ServerAction.addMethod('initDownload', function() {
    var url = this.actionURL + '&' + this.data;
    ajaxIframeDownload(url, {
        onload: function() {
            var str = $('ajax-download-iframe').contentDocument.body.innerHTML;
            try {
                var json = str.evalJSON();
                alert(json.data);
            } catch (ex) {
              // exception here means there is no JSON object
              // which is a good thing, i.e. file did download!
            }
        }
    });
});

repositorySearch.ServerAction.addMethod('_serverErrorHandler', function(ajaxAgent) {
    if (ajaxAgent.getResponseHeader("LoginRequested")) {
        var loginAndGoToSearch = new repositorySearch.RedirectAction(repositorySearch.RedirectType.LOCATION_REDIRECT, {
            flowId: 'searchFlow'
        });

        loginAndGoToSearch.invokeAction();
        return true;
    }

    var resolved = baseErrorHandler(ajaxAgent);

    if (!resolved && ajaxAgent.status == 500) {
        var gotoError = new repositorySearch.RedirectAction(repositorySearch.RedirectType.FLOW_REDIRECT, {
            url: 'flow.html',
            paramsMap: {
                _flowExecutionKey: repositorySearch.flowExecutionKey,
                _eventId: 'error'
            }
        });
        gotoError.invokeAction();
        return true;
    }

    return false;
});

/**
 * Handler for success response.
 *
 * @param data the data received from the server.
 */
repositorySearch.ServerAction.addMethod('onSuccess', doNothing);

/**
 * Handler for error response.
 *
 * @param data the data received from the server.
 */
repositorySearch.ServerAction.addMethod('onError', doNothing);

/**
 * Creates server action instance for repository search actions.
 *
 * @param actionName the name of the search action.
 * @param options {JSON object} - set of options for search action. The number of options and their names are different
 *      for different search actions.
 */
repositorySearch.ServerAction.createSearchAction = function(actionName, options) {
    options.mode = repositorySearch.mode;
    var action = new repositorySearch.ServerAction(actionName, {
        data: options
    });

    action.onSuccess = function(data) {
        if (actionName == repositorySearch.SearchAction.NEXT) {
            repositorySearch.fire(repositorySearch.Event.RESULT_NEXT, data);
        } else if (actionName == repositorySearch.SearchAction.GET_RESOURCE_CHILDREN) {
            repositorySearch.fire(repositorySearch.Event.CHILDREN_LOADED, {
                inputData: options,
                responseData: data
            });
        } else {
            repositorySearch.fire(repositorySearch.Event.RESULT_CHANGED, data);
            repositorySearch.fire(repositorySearch.Event.STATE_CHANGED, data);
            if (repositorySearch.mode == repositorySearch.Mode.SEARCH) {
                repositorySearch.fire(repositorySearch.Event.FILTER_PATH_CHANGED, data);
            }
        }
    };

    action.onError = function(data) {
        repositorySearch.fire(repositorySearch.Event.RESULT_ERROR, data);
    };

    return action;
};

/**
 * Creates server action instance for folder actions.
 *
 * @param actionName the name of the folder action.
 * @param options {JSON object} - set of options for folder action. The number of options and their names are different
 *      for different folder actions.
 */
repositorySearch.ServerAction.createFolderAction = function(actionName, options) {
    var params;
    var eventName;
    var errorEventName;

    if (repositorySearch.FolderAction.DELETE == actionName) {
        params = {
            sourceFolderUri: options.folder.URI
        };
        eventName = repositorySearch.FolderEvent.DELETED;
        errorEventName = repositorySearch.FolderEvent.DELETE_ERROR;
    } else if (repositorySearch.FolderAction.CREATE == actionName) {
        params = {
            destFolderUri : options.toFolder.URI,
            folder: Object.toJSON({
                URI: "",
                label: options.label.stripScripts().escapeHTML(),
                desc: options.desc.stripScripts().escapeHTML()
            })
        };
        eventName = repositorySearch.FolderEvent.CREATED;
        errorEventName = repositorySearch.FolderEvent.CREATE_ERROR;
    } else if (repositorySearch.FolderAction.COPY == actionName) {

        params = {
            destFolderUri : options.toFolder.URI,
            sourceFolderUri: options.folder.URI
        };
        eventName = repositorySearch.FolderEvent.COPIED;
        errorEventName = repositorySearch.FolderEvent.COPY_ERROR;

    } else if (repositorySearch.FolderAction.MOVE == actionName) {

        params = {
            destFolderUri : options.toFolder.URI,
            sourceFolderUri: options.folder.URI
        };
        eventName = repositorySearch.FolderEvent.MOVED;
        errorEventName = repositorySearch.FolderEvent.MOVE_ERROR;
    } else if (repositorySearch.FolderAction.UPDATE == actionName) {

        params = {
            folder: Object.toJSON({
                URI: options.folder.URI,
                label: options.folder.label.stripScripts().escapeHTML(),
                desc: options.folder.description.stripScripts().escapeHTML()
            })
        };
        eventName = repositorySearch.FolderEvent.UPDATED;
        errorEventName = repositorySearch.FolderEvent.UPDATE_ERROR;
    } else if (repositorySearch.ThemeAction.SETTHEME == actionName) {
        params = {
            folderUri: options.folder.URI
        };
        eventName = repositorySearch.ThemeEvent.UPDATED;
    } else if (repositorySearch.ThemeAction.DOWNLOAD_THEME == actionName) {
        params = {
            folderUri: options.folder.URI
        };
        errorEventName = repositorySearch.ThemeEvent.THEME_ERROR;
    }

    if (!params || !eventName || !errorEventName) {
        new Error("Unsupported folder action.");
    }

    var action = new repositorySearch.ServerAction(actionName, {
        data: params
    });

    action.onSuccess = function(data) {
        repositorySearch.fire(eventName, {
            responseData: data,
            inputData: options
        })
    };
    action.onError = function(data) {
        repositorySearch.fire(errorEventName, {
            responseData: data,
            inputData: options
        })
    };

    return action;
};

/**
 * Creates server action instance for folder actions.
 *
 * @param actionName the name of the folder action.
 * @param options {JSON object} - set of options for folder action. The number of options and their names are different
 *      for different folder actions.
 */
repositorySearch.ServerAction.createResourceAction = function(actionName, options) {
    var params;
    var eventName;
    var errorEventName;

    if (repositorySearch.ResourceAction.DELETE == actionName) {
        var list = ResourcesUtils.getResourceUriAndTypeList(options.resources);
        params = {
            selectedResources: list.toJSON()
        };
        eventName = repositorySearch.ResourceEvent.DELETED;
        errorEventName = repositorySearch.ResourceEvent.DELETE_ERROR;

    } else if (repositorySearch.ResourceAction.COPY == actionName) {

        var copyUris = ResourcesUtils.getResourceUris(options.resources);

        params = {
            selectedResources: copyUris.toJSON(),
            destFolderUri : options.folder.URI
        };

        eventName = repositorySearch.ResourceEvent.COPIED;
        errorEventName = repositorySearch.ResourceEvent.COPY_ERROR;
    } else if (repositorySearch.ResourceAction.MOVE == actionName) {

        var moveUris = ResourcesUtils.getResourceUris(options.resources);

        params = {
            selectedResources: moveUris.toJSON(),
            destFolderUri : options.folder.URI
        };

        eventName = repositorySearch.ResourceEvent.MOVED;
        errorEventName = repositorySearch.ResourceEvent.MOVE_ERROR;
    } else if (repositorySearch.ResourceAction.UPDATE == actionName) {
        params = {
            selectedResource: Object.toJSON(options.resource)
        };
        eventName = repositorySearch.ResourceEvent.UPDATED;
        errorEventName = repositorySearch.ResourceEvent.UPDATE_ERROR;
    }

    if (!params || !eventName || !errorEventName) {
        new Error("Unsupported resource action.");
    }

    var action = new repositorySearch.ServerAction(actionName, {
        data: params
    });

    action.onSuccess = function(data) {
        if (repositorySearch.ResourceAction.MOVE == actionName) {
            repositorySearch.CopyMoveController.cancel();
        }

        repositorySearch.fire(eventName, {
            responseData: data,
            inputData: options
        })
    };
    action.onError = function(data) {
        repositorySearch.fire(errorEventName, {
            responseData: data,
            inputData: options
        })
    };

    return action;
};

/**
 * Creates server action instance for permissions actions.
 *
 * @param actionName the name of the permission action.
 * @param options {JSON object} - set of options for permission action. The number of options and their names are different
 *      for different permission actions.
 */
repositorySearch.ServerAction.createPermissionAction = function(actionName, options) {
    var action = new repositorySearch.ServerAction(actionName, {
        data: options
    });

    var successEvent = actionName == repositorySearch.PermissionAction.UPDATE ?
            repositorySearch.PermissionEvent.UPDATED :
            repositorySearch.PermissionEvent.LOADED;

    action.onSuccess = function(data) {
        repositorySearch.fire(successEvent, {
            responseData: data,
            inputData: options,
            doSet: actionName != repositorySearch.PermissionAction.NEXT
        })
    };

    action.onError = function(data) {
        repositorySearch.fire(repositorySearch.PermissionEvent.ERROR, data);
    };

    return action;
};

/**
 * Creates server action instance for folder actions.
 *
 * @param type {} type of redirect. All supported types defined in {@see repositorySearch.RedirectType} map.
 * @param options Set of options for action:
 * <ul>
 * <li>url {String} URL</li>
 * <li>flowId {String} ID of the flow</li>
 * <li>paramsMap {JSON Object} map of parameters</li>
 * <li>encode {Boolean} </li>
 * </ul>
 */
repositorySearch.RedirectAction = function(type, options) {
    this.type = type;
    this.flowId = options.flowId;
    this.url = options.url ? options.url : (this.flowId ? this.FLOW_URL : undefined);
    this.paramsMap = options.paramsMap || {};
    this.encode = options.encode;

    if (this.type !== repositorySearch.RedirectType.FLOW_REDIRECT && this.url === this.FLOW_URL) {
        this.paramsMap['_flowId'] = this.flowId;
    }
};

repositorySearch.RedirectAction.addMethod('FLOW_URL', "flow.html");

repositorySearch.RedirectAction.addMethod('_serializeParams', function(paramsMap, encode) {
    if (paramsMap) {
        var result = '';

        for (var name in paramsMap) {
            if (!Object.isUndefined(name)) {
                result += '&' + name + '=' + (encode ? encodeURIComponent(paramsMap[name]) : paramsMap[name]);
            }
        }

        return (result && result.length > 0) ? result.substring(1) : '';
    } else {
        return '';
    }
});

repositorySearch.RedirectAction.addMethod('invokeAction', function() {
    if(this.type === repositorySearch.RedirectType.FLOW_REDIRECT) {

        var form = $('redirectForm');
        var flowParams = $('flowParams');

        flowParams.setValue(this.flowId + '?' + this._serializeParams(this.paramsMap, this.encode));

        var action = new repositorySearch.ServerAction("isServerAvailable", { data: {} });

        action.onSuccess = function(data) {
            if(data.strip() == "Yes") {
                form.submit();
                repositorySearch.fire(repositorySearch.Event.FLOW_REDIRECT_RUNNING, data);
            } else {
                repositorySearch.fire(repositorySearch.Event.REDIRECT_ERROR, data);
            }
        };

        action.onError = function(data) {
            repositorySearch.fire(repositorySearch.Event.REDIRECT_ERROR, data);
        };

        action.invokeAction();

    } else if(this.type === repositorySearch.RedirectType.LOCATION_REDIRECT) {

        document.location = this.url + '?' + this._serializeParams(this.paramsMap);

    } else if(this.type === repositorySearch.RedirectType.WINDOW_REDIRECT) {

        var w = window.open();
        w.opener = null;
        w.document.location = this.url + '?' + this._serializeParams(this.paramsMap);
    }
});

repositorySearch.runActionFactory = {
    "ReportUnit": function(resource, inNewTab) {

        var type = inNewTab ?
                   repositorySearch.RedirectType.WINDOW_REDIRECT : repositorySearch.RedirectType.FLOW_REDIRECT;

        return new repositorySearch.RedirectAction(type, {
            url: "flow.html",
            flowId: 'viewReportFlow',
            paramsMap: {
                _flowId: 'viewReportFlow',
                reportUnit: resource.URIString,
                standAlone: true,
                ParentFolderUri: resource.parentFolder
            }
        });
    },

    "AdhocReportUnit": function(resource, inNewTab) {

        var type = inNewTab ?
                   repositorySearch.RedirectType.WINDOW_REDIRECT : repositorySearch.RedirectType.FLOW_REDIRECT;

        return new repositorySearch.RedirectAction(type, {
            url: "flow.html",
            flowId: 'viewAdhocReportFlow',
            paramsMap: {
                reportUnit: resource.URIString,
                standAlone: true,
                ParentFolderUri: resource.parentFolder
            }
        });
    },

    "OlapUnit": function(resource, inNewTab) {

        var type = inNewTab ?
                   repositorySearch.RedirectType.WINDOW_REDIRECT : repositorySearch.RedirectType.LOCATION_REDIRECT;

        return new repositorySearch.RedirectAction(type, {
            url: 'olap/viewOlap.html',
            paramsMap: {
                name: resource.URIString,
                'new': true,
                parentFlow: 'searchFlow',
                ParentFolderUri: resource.parentFolder
            }
        });
    },

    "ContentResource": function(resource, inNewTab) {

        var type = inNewTab ?
                   repositorySearch.RedirectType.WINDOW_REDIRECT : repositorySearch.RedirectType.LOCATION_REDIRECT;

        return new repositorySearch.RedirectAction(type, {
            url: "fileview/fileview" + resource.URIString,
            paramsMap: {}
        });
    },

    "DashboardResource": function(resource, inNewTab) {
        var type = inNewTab ?
                   repositorySearch.RedirectType.WINDOW_REDIRECT : repositorySearch.RedirectType.FLOW_REDIRECT;

        return new repositorySearch.RedirectAction(type, {
            url: "flow.html",
            flowId: 'dashboardRuntimeFlow',
            paramsMap: {
                dashboardResource: resource.URIString
            }
        });
    },

    "ReportOptions": function(resource, inNewTab) {
        var params = {
            reportOptionsURI: resource.URIString,
            standAlone: true,
            ParentFolderUri: resource.parentFolder
        };

        var flow;

        var parentResource = resource.parentResource;
        if (parentResource && parentResource.typeEquals(repositorySearch.ResourceType.ADHOC_REPORT_UNIT)) {

            flow = 'viewAdhocReportFlow';
            params.reportUnit = parentResource.URIString;
        } else {
            flow = 'viewReportFlow';
        }

        var type = inNewTab ?
                   repositorySearch.RedirectType.WINDOW_REDIRECT : repositorySearch.RedirectType.FLOW_REDIRECT;

        return new repositorySearch.RedirectAction(type, {
            url: "flow.html",
            flowId: flow,
            paramsMap: params
        });
    }
};
/**
 * Creates server action instance for folder actions.
 *
 * @param resource {Resource} the name of the folder action.
 */
repositorySearch.RedirectAction.createRunResourceAction = function(resource, inNewTab) {
    if (!resource) {
        resource = resource ? resource : repositorySearch.model.getSelectedResources()[0];
    }

    var factoryMethod = repositorySearch.runActionFactory[resource.typeSuffix()];

    if (factoryMethod) {
        return factoryMethod(resource, inNewTab);
    } else {
        return new repositorySearch.Action(function() {
            alert("Run action for resource type '" + resource.resourceType + "' is not implemented!");
        });
    }
};

repositorySearch.editActionFactory = {
    "ReportUnit": function(resource, actionType) {
        return new repositorySearch.RedirectAction(actionType, {
            flowId: 'reportUnitFlow',
            paramsMap: {
                selectedResource: resource.URIString,
                ParentFolderUri: resource.parentFolder
            }
        });
    },

    "AdhocReportUnit": function(resource, actionType) {
        return repositorySearch.editActionFactory["ReportUnit"](resource, actionType);
    },

    "DataDefinerUnit": function(resource, actionType) {
        return repositorySearch.editActionFactory["ReportUnit"](resource, actionType);
    },

    "OlapUnit": function(resource, actionType) {
        return new repositorySearch.RedirectAction(actionType, {
            flowId: 'olapUnitFlow',
            paramsMap: {
                resource: resource.URIString,
                isEdit: 'edit',
                ParentFolderUri: resource.parentFolder
            }
        });
    },

    "DashboardResource": function(resource, actionType) {
        return new repositorySearch.RedirectAction(actionType, {
            flowId: 'dashboardRuntimeFlow',
            paramsMap: {
                dashboardResource: resource.URIString
            }
        });
    },

    "ReportOptions": function(resource, actionType) {
        return new repositorySearch.RedirectAction(actionType, {
            flowId: "reportOptionsEditFlow",
            paramsMap: {
                reportOptionsURI: resource.URIString,
                ParentFolderUri: resource.parentFolder
            }
        });
    },

    "JdbcReportDataSource": function(resource, actionType) {
        return new repositorySearch.RedirectAction(actionType, {
            flowId: "addDataSourceFlow",
            paramsMap: {
                resource: resource.URIString,
                ParentFolderUri: resource.parentFolder
            }
        });
    },

    "JndiJdbcReportDataSource": function(resource, actionType) {
        return repositorySearch.editActionFactory["JdbcReportDataSource"](resource, actionType);
    },

    "CustomReportDataSource": function(resource, actionType) {
        return repositorySearch.editActionFactory["JdbcReportDataSource"](resource, actionType);
    },

    "BeanReportDataSource": function(resource, actionType) {
        return repositorySearch.editActionFactory["JdbcReportDataSource"](resource, actionType);
    },

    "Query": function(resource, actionType) {
        return new repositorySearch.RedirectAction(actionType, {
            flowId: "queryFlow",
            paramsMap: {
                currentQuery: resource.URIString,
                isEdit: true,
                ParentFolderUri: resource.parentFolder
            }
        });
    },

    "InputControl": function(resource, actionType) {
        return new repositorySearch.RedirectAction(actionType, {
            flowId: "addInputControlFlow",
            paramsMap: {
                resource: resource.URIString,
                ParentFolderUri: resource.parentFolder
            }
        });
    },

    "ListOfValues": function(resource, actionType) {
        return new repositorySearch.RedirectAction(actionType, {
            flowId: "addListOfValuesFlow",
            paramsMap: {
                resource: resource.URIString,
                isEdit: 'edit',
                ParentFolderUri: resource.parentFolder
            }
        });
    },

    "DataType": function(resource, actionType) {
        return new repositorySearch.RedirectAction(actionType, {
            flowId: "dataTypeFlow",
            paramsMap: {
                resource: resource.URIString,
                isEdit: 'edit',
                ParentFolderUri: resource.parentFolder
            }
        });
    },

    "MondrianConnection": function(resource, actionType) {
        return new repositorySearch.RedirectAction(actionType, {
            flowId: "olapClientConnectionFlow",
            paramsMap: {
                selectedResource: resource.URIString,
                isEdit: 'edit',
                ParentFolderUri: resource.parentFolder
            }
        });
    },

    "SecureMondrianConnection": function(resource, actionType) {
        return repositorySearch.editActionFactory["MondrianConnection"](resource, actionType);
    },

    "XMLAConnection": function(resource, actionType) {
        return repositorySearch.editActionFactory["MondrianConnection"](resource, actionType);
    },

    "MondrianXMLADefinition": function(resource, actionType) {
        return new repositorySearch.RedirectAction(actionType, {
            flowId: "mondrianXmlaSourceFlow",
            paramsMap: {
                selectedResource: resource.URIString,
                isEdit: 'edit',
                ParentFolderUri: resource.parentFolder
            }
        });
    },

    "FileResource": function(resource, actionType) {
        return new repositorySearch.RedirectAction(actionType, {
            flowId: "addFileResourceFlow",
            paramsMap: {
                selectedResource: resource.URIString,
                ParentFolderUri: resource.parentFolder
            }
        });
    },

    "SemanticLayerDataSource": function(resource, actionType) {
        return new repositorySearch.RedirectAction(actionType, {
            flowId: "createSLDatasourceFlow",
            paramsMap: {
                uri: resource.URIString,
                ParentFolderUri: resource.parentFolder
            }
        });
    }
};

/**
 * Creates edit resource actions.
 *
 * @param resource {Resource} the name of the folder action.
 */
repositorySearch.RedirectAction.createEditResourceAction = function(resource, inNewTab) {
    if (!resource) {
        resource = repositorySearch.model.getSelectedResources()[0];
    }

    var type = inNewTab ?
                   repositorySearch.RedirectType.WINDOW_REDIRECT : repositorySearch.RedirectType.FLOW_REDIRECT;

    var factoryMethod = repositorySearch.editActionFactory[resource.typeSuffix()];

    if (factoryMethod) {
        return factoryMethod(resource, type);
    } else {
        return new repositorySearch.Action(function() {
            alert("Edit action for resource type '" + resource.resourceType + "' is not implemented!");
        });
    }
};

repositorySearch.openActionFactory = {
    "DashboardResource": function(resource, actionType) {
        return new repositorySearch.RedirectAction(actionType, {
            flowId: 'dashboardDesignerFlow',
            paramsMap: {
                resource: resource.URIString,
                ParentFolderUri: resource.parentFolder
            }
        });
    },

    "DataDefinerUnit": function(resource, actionType) {
        return new repositorySearch.RedirectAction(actionType, {
            flowId: 'queryBuilderFlow',
            paramsMap: {
                uri: resource.URIString,
                ParentFolderUri: resource.parentFolder
            }
        });
    },

    "AdhocReportUnit": function(resource, actionType) {
        return new repositorySearch.RedirectAction(actionType, {
            flowId: 'adhocFlow',
            paramsMap: {
                resource: resource.URIString,
                ParentFolderUri: resource.parentFolder
            }
        });
    }
};

/**
 * Creates open action instance for resource actions.
 *
 * @param resource {Resource} the name of the folder action.
 */
repositorySearch.RedirectAction.createOpenResourceAction = function(resource, inNewTab) {
    if (!resource) {
        resource = repositorySearch.model.getSelectedResources()[0];
    }

    var type = inNewTab ?
               repositorySearch.RedirectType.WINDOW_REDIRECT : repositorySearch.RedirectType.FLOW_REDIRECT;

    var factoryMethod = repositorySearch.openActionFactory[resource.typeSuffix()];

    if (factoryMethod) {
        return factoryMethod(resource, type);
    } else {
        return new repositorySearch.Action(function() {
            alert("Open action for resource type '" + resource.resourceType + "' is not implemented!");
        });
    }
};

/**
 * Creates run in background action instance for resource actions.
 *
 * @param resource {Resource} the name of the folder action.
 */
repositorySearch.RedirectAction.createRunInBackgroundResourceAction = function() {
   var resource = repositorySearch.model.getSelectedResources()[0];

    var params = {
        isNewModeRequest: true,
        isRunNowModeRequest: true,
        reportUnitURIRequest: resource.URIString,
        ParentFolderUri: resource.parentFolder
    };

    if (resource.resourceType.endsWith(".ReportUnit") ||
        resource.resourceType.endsWith(".AdhocReportUnit")) {

        params.reportUnitURIRequest = resource.URIString;

    } else if (resource.resourceType.endsWith(".ReportOptions")) {

        params.reportOptionsURI = resource.URIString;

    } else {
        return null;
    }

    return new repositorySearch.RedirectAction(repositorySearch.RedirectType.FLOW_REDIRECT, {
        flowId: 'reportJobFlow',
        paramsMap: params
    });
};

/**
 * Creates run in background action instance for resource.
 *
 * @param resource {Resource} the name of the folder action.
 */
repositorySearch.RedirectAction.createScheduleAction = function() {
   var resource = repositorySearch.model.getSelectedResources()[0];

    var params = {
        ParentFolderUri: resource.parentFolder
    };

    if (resource.resourceType.endsWith(".ReportUnit") ||
        resource.resourceType.endsWith(".AdhocReportUnit")) {

        params.reportUnitURI = resource.URIString;

    } else if (resource.resourceType.endsWith(".ReportOptions")) {

        params.reportOptionsURI = resource.URIString;

    } else {
        return null;
    }

    return new repositorySearch.RedirectAction(repositorySearch.RedirectType.FLOW_REDIRECT, {
        flowId: 'reportSchedulingFlow',
        paramsMap: params
    });
};

repositorySearch.createActionFactory = {

    "OlapClientConnection": function(folder) {
        return new repositorySearch.RedirectAction(repositorySearch.RedirectType.FLOW_REDIRECT, {
            flowId: 'olapClientConnectionFlow',
            paramsMap: {
                ParentFolderUri: folder.URI
            }
        });
    },

    "OlapUnit": function(folder) {
        return new repositorySearch.RedirectAction(repositorySearch.RedirectType.FLOW_REDIRECT, {
            flowId: 'olapUnitFlow',
            paramsMap: {
                ParentFolderUri: folder.URI
            }
        });
    },

    "ReportDataSource": function(folder) {
        return new repositorySearch.RedirectAction(repositorySearch.RedirectType.FLOW_REDIRECT, {
            flowId: 'addDataSourceFlow',
            paramsMap: {
                ParentFolderUri: folder.URI
            }
        });
    },

    "SemanticLayerDataSource": function(folder) {
        return new repositorySearch.RedirectAction(repositorySearch.RedirectType.FLOW_REDIRECT, {
            flowId: 'createSLDatasourceFlow',
            paramsMap: {
                ParentFolderUri: folder.URI
            }
        });
    },

    "FileResource": function(folder, fileType) {
        return new repositorySearch.RedirectAction(repositorySearch.RedirectType.FLOW_REDIRECT, {
//            flowId: 'fileResourceFlow', // old
            flowId: 'addFileResourceFlow', // new
            paramsMap: {
                expectedFileType: fileType,
                parentFolder: folder.URI
            }
        });
    },

    "ReportUnit": function(folder) {
        return new repositorySearch.RedirectAction(repositorySearch.RedirectType.FLOW_REDIRECT, {
            flowId: 'reportUnitFlow',
            paramsMap: {
                ParentFolderUri: folder.URI
            }
        });
    },

    "Query": function(folder) {
        return new repositorySearch.RedirectAction(repositorySearch.RedirectType.FLOW_REDIRECT, {
            flowId: 'queryFlow',
            paramsMap: {
                ParentFolderUri: folder.URI
            }
        });
    },

    "InputControl": function(folder) {
        return new repositorySearch.RedirectAction(repositorySearch.RedirectType.FLOW_REDIRECT, {
            flowId: 'addInputControlFlow',
            paramsMap: {
                ParentFolderUri: folder.URI
            }
        });
    },

    "DataType": function(folder) {
        return new repositorySearch.RedirectAction(repositorySearch.RedirectType.FLOW_REDIRECT, {
            flowId: 'dataTypeFlow',
            paramsMap: {
                ParentFolderUri: folder.URI
            }
        });
    },

    "ListOfValues": function(folder) {
        return new repositorySearch.RedirectAction(repositorySearch.RedirectType.FLOW_REDIRECT, {
            flowId: 'addListOfValuesFlow',
            paramsMap: {
                ParentFolderUri: folder.URI
            }
        });
    },

    "XMLAConnection": function(folder) {
        return new repositorySearch.RedirectAction(repositorySearch.RedirectType.FLOW_REDIRECT, {
            flowId: 'mondrianXmlaSourceFlow',
            paramsMap: {
                ParentFolderUri: folder.URI
            }
        });
    }
};

repositorySearch.RedirectAction.createCreateResourceAction = function(resourceTypeSuffix, fileType) {

    var folder = repositorySearch.model.getContextFolder();
    var factoryMethod = repositorySearch.createActionFactory[resourceTypeSuffix];

    if (factoryMethod) {
        return factoryMethod(folder, fileType);
    } else {
        return new repositorySearch.Action(function() {
            alert("Create action for resource type suffix '" + resourceTypeSuffix + "' is not implemented!");
        });
    }

};

repositorySearch.confirmAndLeave = function() {

    return new repositorySearch.Action(function() {
        return (!isPropertiesChanged() && !isPermissionsChanged()) ||
                confirm(repositorySearch.getMessage("RM_CANCEL_EDIT_MESSAGE"));
    }).invokeAction();

};
