/*
 * Copyright 2015-2017 Atomist Inc.
 *
 * Licensed 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.
 */

import { TreeNode, GraphNode, FormatInfo, PathExpressionEngine } from "@atomist/rug/tree/PathExpression";
import { ProjectContext } from "@atomist/rug/operations/ProjectEditor";
import { ArtifactContainer } from "./ArtifactContainer";
import { ProjectView } from "./ProjectView";
import { ArtifactContainerView } from "./ArtifactContainerView";
import { ChangeLogging } from "./ChangeLogging";
import { MutableView } from "./MutableView";
export { Project };

/**
 * Type for a project. Supports global operations. Consider using file and other lower types by preference as projectoperations can be inefficient.
 */
interface Project extends ArtifactContainer, ProjectView, ArtifactContainerView, ChangeLogging, MutableView {

    /**
     * Create a directory
     *
     * @param name {string} The name of the directory being added
     * @param parentPath {string} The path under which the directory should be created
     */
    addDirectory(name: string, parentPath: string): void;

    /**
     * Create a directory
     *
     * @param directoryPath {string} The path under which the directory and any missing intermediate directories will be created
     */
    addDirectoryAndIntermediates(directoryPath: string): void;

    /**
     * Add the given executable file to the project. Path can contain /s. Content is a literal string
     *
     * @param path {string} The path to use
     * @param content {string} The content to be placed in the new file
     */
    addExecutableFile(path: string, content: string): void;

    /**
     * Add the given file to the project. Path can contain /s. Content is a literal string
     *
     * @param path {string} The path to use
     * @param content {string} The content to be placed in the new file
     */
    addFile(path: string, content: string): void;

    /**
     * Copy the given file from the editor's backing archive to the same path in project being edited. Fail the editor if it isn't found or if the destination already exists
     *
     * @param sourcePath {string} Source path
     */
    copyEditorBackingFileOrFail(sourcePath: string): void;

    /**
     * Copy the given file from the editor's backing archive. Fail the editor if it isn't found or if the destination already exists
     *
     * @param sourcePath {string} Source path
     * @param destinationPath {string} Destination path
     */
    copyEditorBackingFileOrFailToDestination(sourcePath: string, destinationPath: string): void;

    /**
     * Copy the given file from the editor's backing archive. Fail the editor if it isn't found or if the destination already exists
     *
     * @param sourcePath {string} Source directory
     * @param destinationPath {string} Destination path
     */
    copyEditorBackingFilesOrFail(sourcePath: string, destinationPath: string): void;

    /**
     * Copy the given files from the editor's backing archive under the given directory into the same directory in the project being edited.
     *
     * @param sourcePath {string} Source directory
     */
    copyEditorBackingFilesPreservingPath(sourcePath: string): void;

    /**
     * Copy the given files from the editor's backing archive under the given path. Take the relative paths and place under new destination path
     *
     * @param sourcePath {string} Source directory
     * @param destinationPath {string} Destination path
     */
    copyEditorBackingFilesWithNewRelativePath(sourcePath: string, destinationPath: string): void;

    /**
     * Copy the given files from the editor's backing archive project to the project being edited. Doesn't copy Atomist content.
     *
     */
    copyEditorBackingProject(): void;

    /**
     * Copy the given file in the target project. It is not an error if it doesn't exist
     *
     * @param sourcePath {string} Source path
     * @param destinationPath {string} Destination path
     */
    copyFile(sourcePath: string, destinationPath: string): void;

    /**
     * Copy the given file in the target project. Fail the editor if it isn't found or if the destination already exists
     *
     * @param sourcePath {string} Source path
     * @param destinationPath {string} Destination path
     */
    copyFileOrFail(sourcePath: string, destinationPath: string): void;

    /**
     * Deletes a directory with the given path
     *
     * @param path {string} The path to use
     */
    deleteDirectory(path: string): void;

    /**
     * Delete the given file from the project. Path can contain /s.
     *
     * @param path {string} The path to use
     */
    deleteFile(path: string): void;

    /**
     * Edit with the given editor
     *
     * @param editorName {string} Name of the editor to invoke
     * @param params {any} Parameters to pass to the editor
     */
    editWith(editorName: string, params: any): void;

    /**
     * Makes a file executable
     *
     * @param path {string} The path to use
     */
    makeExecutable(path: string): void;

    /**
     * Merge the given template to the given output path.
     *
     * @param template {string} The name of the template within the backing Rug archive, under /.atomist / templates
     * @param path {string} The path that will be the merged path within the output project.
     * @param parameters {any} Parameters
     */
    merge(template: string, path: string, parameters: any): void;

    /**
     * Merge templates from the specified directory in the backing archive, under /.atomist/templates, to the given output path in the project being edited.
     *
     * @param templatesPath {string} Source template path where content will be used to merge into target project
     * @param outputPath {string} The destination path within the destination project
     * @param ic {any} Parameters to the template
     */
    mergeTemplates(templatesPath: string, outputPath: string, ic: any): void;

    /**
     * Move the contents of this project under the given path, preserving its present path under that
     *
     * @param path {string} The root path to move the file to
     */
    moveUnder(path: string): void;

    /**
     * Don't use. Merely intended to simplify the life of the Rug to TypeScript transpiler.
     *
     * @returns {Project[]}
     */
    projects(): Project[];

    /**
     * Replace all occurrences of the given regular expression in this project
     *
     * @param regexp {string} The regular expression to search for
     * @param replacement {string} The string to replace matches with
     */
    regexpReplace(regexp: string, replacement: string): void;

    /**
     * Replace all occurrences of the given string literal in this project. Use with care!
     *
     * @param literal {string} The string to look for
     * @param replaceWith {string} The string to replace matches with
     */
    replace(literal: string, replaceWith: string): void;

    /**
     * Globally replace all occurrences of the given string literal in file paths in this project
     *
     * @param literal {string} The string to search for
     * @param replacement {string} The string to replace in the paths if found
     */
    replaceInPath(literal: string, replacement: string): void;

}
