/*
 * 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 * as issueApi from "../Issue";
import { Comment } from "./Comment";
import { Commit } from "./Commit";
import { GitHubId } from "./GitHubId";
import { Label } from "./Label";
import { Repo } from "./Repo";
export { Issue };

/**
 * Type Issue
 * Generated class exposing Atomist Cortex.
 * Fluent builder style class for use in testing and query by example.
 */
class Issue implements issueApi.Issue {

    private _action: string;
    private _assignees: GitHubId[];
    private _body: string;
    private _closedAt: string;
    private _closedBy: GitHubId;
    private _comments: Comment[];
    private _createdAt: string;
    private _id: string;
    private _labels: Label[];
    private _lastAssignedBy: GitHubId;
    private _name: string;
    private _number: number;
    private _openedBy: GitHubId;
    private _repo: Repo;
    private _resolvingCommits: Commit[];
    private _state: "open" | "closed";
    private _timestamp: string;
    private _title: string;
    private _updatedAt: string;

    private _nodeName = "Issue";
    private _nodeTags = [ "Issue", "-dynamic" ];

    /**
     * Implementation of GraphNode interface method.
     * For infrastructure, not user use
     */
    public nodeName(): string {
        return this._nodeName;
    }

    /**
     * Implementation of GraphNode interface method.
     * For infrastructure, not user use
     */
    public nodeTags(): string[] {
        return this._nodeTags;
    }

    /**
     * action
     *
     * @property {string} action
     */
    get action(): string {
        if (this._action === undefined) {
            throw new Error(`Please use the relevant builder method to set property [action] on stub ` +
                `[Issue] before accessing it. It's probably called [withAction]`);
        }
        return this._action;
    }

    /**
     * Fluent builder method to set the action property
     */
    public withAction(action_: string) {
        this._action = action_;
        return this;
    }

    /**
     * assignees - Issue -> GitHubId
     *
     * @property {GitHubId[]} assignees
     */
    get assignees(): GitHubId[] {
        if (this._assignees === undefined) {
            throw new Error(`Please use the relevant builder method to set property [assignees] on stub ` +
                `[Issue] before accessing it. It's probably called [withAssignees]`);
        }
        return this._assignees;
    }

    /**
     * Fluent builder method to add an element to the assignees array
     */
    public addAssignees(...assignees_: GitHubId[]) {
        if (this._assignees === undefined) {
            this._assignees = [];
        }
        this._assignees = this._assignees.concat(assignees_);
        return this;
    }

    /**
     * body
     *
     * @property {string} body
     */
    get body(): string {
        if (this._body === undefined) {
            throw new Error(`Please use the relevant builder method to set property [body] on stub ` +
                `[Issue] before accessing it. It's probably called [withBody]`);
        }
        return this._body;
    }

    /**
     * Fluent builder method to set the body property
     */
    public withBody(body_: string) {
        this._body = body_;
        return this;
    }

    /**
     * closedAt
     *
     * @property {string} closedAt
     */
    get closedAt(): string {
        if (this._closedAt === undefined) {
            throw new Error(`Please use the relevant builder method to set property [closedAt] on stub ` +
                `[Issue] before accessing it. It's probably called [withClosedAt]`);
        }
        return this._closedAt;
    }

    /**
     * Fluent builder method to set the closedAt property
     */
    public withClosedAt(closedAt_: string) {
        this._closedAt = closedAt_;
        return this;
    }

    /**
     * closedBy - Issue -> GitHubId
     *
     * @property {GitHubId} closedBy
     */
    get closedBy(): GitHubId {
        if (this._closedBy === undefined) {
            throw new Error(`Please use the relevant builder method to set property [closedBy] on stub ` +
                `[Issue] before accessing it. It's probably called [withClosedBy]`);
        }
        return this._closedBy;
    }

    /**
     * Fluent builder method to set the closedBy property
     */
    public withClosedBy(closedBy_: GitHubId) {
        this._closedBy = closedBy_;
        return this;
    }

    /**
     * comments - Issue -> Comment
     *
     * @property {Comment[]} comments
     */
    get comments(): Comment[] {
        if (this._comments === undefined) {
            throw new Error(`Please use the relevant builder method to set property [comments] on stub ` +
                `[Issue] before accessing it. It's probably called [withComments]`);
        }
        return this._comments;
    }

    /**
     * Fluent builder method to add an element to the comments array
     */
    public addComments(...comments_: Comment[]) {
        if (this._comments === undefined) {
            this._comments = [];
        }
        this._comments = this._comments.concat(comments_);
        return this;
    }

    /**
     * createdAt
     *
     * @property {string} createdAt
     */
    get createdAt(): string {
        if (this._createdAt === undefined) {
            throw new Error(`Please use the relevant builder method to set property [createdAt] on stub ` +
                `[Issue] before accessing it. It's probably called [withCreatedAt]`);
        }
        return this._createdAt;
    }

    /**
     * Fluent builder method to set the createdAt property
     */
    public withCreatedAt(createdAt_: string) {
        this._createdAt = createdAt_;
        return this;
    }

    /**
     * id
     *
     * @property {string} id
     */
    get id(): string {
        if (this._id === undefined) {
            throw new Error(`Please use the relevant builder method to set property [id] on stub ` +
                `[Issue] before accessing it. It's probably called [withId]`);
        }
        return this._id;
    }

    /**
     * Fluent builder method to set the id property
     */
    public withId(id_: string) {
        this._id = id_;
        return this;
    }

    /**
     * labels - Issue -> Label
     *
     * @property {Label[]} labels
     */
    get labels(): Label[] {
        if (this._labels === undefined) {
            throw new Error(`Please use the relevant builder method to set property [labels] on stub ` +
                `[Issue] before accessing it. It's probably called [withLabels]`);
        }
        return this._labels;
    }

    /**
     * Fluent builder method to add an element to the labels array
     */
    public addLabels(...labels_: Label[]) {
        if (this._labels === undefined) {
            this._labels = [];
        }
        this._labels = this._labels.concat(labels_);
        return this;
    }

    /**
     * lastAssignedBy - Issue -> GitHubId
     *
     * @property {GitHubId} lastAssignedBy
     */
    get lastAssignedBy(): GitHubId {
        if (this._lastAssignedBy === undefined) {
            throw new Error(`Please use the relevant builder method to set property [lastAssignedBy] on stub ` +
                `[Issue] before accessing it. It's probably called [withLastAssignedBy]`);
        }
        return this._lastAssignedBy;
    }

    /**
     * Fluent builder method to set the lastAssignedBy property
     */
    public withLastAssignedBy(lastAssignedBy_: GitHubId) {
        this._lastAssignedBy = lastAssignedBy_;
        return this;
    }

    /**
     * name
     *
     * @property {string} name
     */
    get name(): string {
        if (this._name === undefined) {
            throw new Error(`Please use the relevant builder method to set property [name] on stub ` +
                `[Issue] before accessing it. It's probably called [withName]`);
        }
        return this._name;
    }

    /**
     * Fluent builder method to set the name property
     */
    public withName(name_: string) {
        this._name = name_;
        return this;
    }

    /**
     * number
     *
     * @property {number} number
     */
    get number(): number {
        if (this._number === undefined) {
            throw new Error(`Please use the relevant builder method to set property [number] on stub ` +
                `[Issue] before accessing it. It's probably called [withNumber]`);
        }
        return this._number;
    }

    /**
     * Fluent builder method to set the number property
     */
    public withNumber(number_: number) {
        this._number = number_;
        return this;
    }

    /**
     * openedBy - Issue -> GitHubId
     *
     * @property {GitHubId} openedBy
     */
    get openedBy(): GitHubId {
        if (this._openedBy === undefined) {
            throw new Error(`Please use the relevant builder method to set property [openedBy] on stub ` +
                `[Issue] before accessing it. It's probably called [withOpenedBy]`);
        }
        return this._openedBy;
    }

    /**
     * Fluent builder method to set the openedBy property
     */
    public withOpenedBy(openedBy_: GitHubId) {
        this._openedBy = openedBy_;
        return this;
    }

    /**
     * repo - Issue -> Repo
     *
     * @property {Repo} repo
     */
    get repo(): Repo {
        if (this._repo === undefined) {
            throw new Error(`Please use the relevant builder method to set property [repo] on stub ` +
                `[Issue] before accessing it. It's probably called [withRepo]`);
        }
        return this._repo;
    }

    /**
     * Fluent builder method to set the repo property
     */
    public withRepo(repo_: Repo) {
        this._repo = repo_;
        return this;
    }

    /**
     * resolvingCommits - Issue -> Commit
     *
     * @property {Commit[]} resolvingCommits
     */
    get resolvingCommits(): Commit[] {
        if (this._resolvingCommits === undefined) {
            throw new Error(`Please use the relevant builder method to set property [resolvingCommits] on stub ` +
                `[Issue] before accessing it. It's probably called [withResolvingCommits]`);
        }
        return this._resolvingCommits;
    }

    /**
     * Fluent builder method to add an element to the resolvingCommits array
     */
    public addResolvingCommits(...resolvingCommits_: Commit[]) {
        if (this._resolvingCommits === undefined) {
            this._resolvingCommits = [];
        }
        this._resolvingCommits = this._resolvingCommits.concat(resolvingCommits_);
        return this;
    }

    /**
     * state
     *
     * @property {"open" | "closed"} state
     */
    get state(): "open" | "closed" {
        if (this._state === undefined) {
            throw new Error(`Please use the relevant builder method to set property [state] on stub ` +
                `[Issue] before accessing it. It's probably called [withState]`);
        }
        return this._state;
    }

    /**
     * Fluent builder method to set the state property
     */
    public withState(state_: "open" | "closed") {
        this._state = state_;
        return this;
    }

    /**
     * timestamp
     *
     * @property {string} timestamp
     */
    get timestamp(): string {
        if (this._timestamp === undefined) {
            throw new Error(`Please use the relevant builder method to set property [timestamp] on stub ` +
                `[Issue] before accessing it. It's probably called [withTimestamp]`);
        }
        return this._timestamp;
    }

    /**
     * Fluent builder method to set the timestamp property
     */
    public withTimestamp(timestamp_: string) {
        this._timestamp = timestamp_;
        return this;
    }

    /**
     * title
     *
     * @property {string} title
     */
    get title(): string {
        if (this._title === undefined) {
            throw new Error(`Please use the relevant builder method to set property [title] on stub ` +
                `[Issue] before accessing it. It's probably called [withTitle]`);
        }
        return this._title;
    }

    /**
     * Fluent builder method to set the title property
     */
    public withTitle(title_: string) {
        this._title = title_;
        return this;
    }

    /**
     * updatedAt
     *
     * @property {string} updatedAt
     */
    get updatedAt(): string {
        if (this._updatedAt === undefined) {
            throw new Error(`Please use the relevant builder method to set property [updatedAt] on stub ` +
                `[Issue] before accessing it. It's probably called [withUpdatedAt]`);
        }
        return this._updatedAt;
    }

    /**
     * Fluent builder method to set the updatedAt property
     */
    public withUpdatedAt(updatedAt_: string) {
        this._updatedAt = updatedAt_;
        return this;
    }

}
