/*
 * 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 pullRequestApi from "../PullRequest";
import { Branch } from "./Branch";
import { Build } from "./Build";
import { Comment } from "./Comment";
import { Commit } from "./Commit";
import { GitHubId } from "./GitHubId";
import { Label } from "./Label";
import { Repo } from "./Repo";
import { Review } from "./Review";
export { PullRequest };

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

    private _assignees: GitHubId[];
    private _author: GitHubId;
    private _base: Commit;
    private _baseBranchName: string;
    private _body: string;
    private _branch: Branch;
    private _branchName: string;
    private _builds: Build[];
    private _closedAt: string;
    private _comments: Comment[];
    private _commits: Commit[];
    private _createdAt: string;
    private _head: Commit;
    private _id: string;
    private _labels: Label[];
    private _lastAssignedBy: GitHubId;
    private _mergeCommit: Commit;
    private _merged: boolean;
    private _mergedAt: string;
    private _merger: GitHubId;
    private _name: string;
    private _number: number;
    private _repo: Repo;
    private _reviewers: GitHubId[];
    private _reviews: Review[];
    private _state: string;
    private _timestamp: string;
    private _title: string;
    private _updatedAt: string;

    private _nodeName = "PullRequest";
    private _nodeTags = [ "PullRequest", "-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;
    }

    /**
     * assignees - PullRequest -> 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 ` +
                `[PullRequest] 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;
    }

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

    /**
     * Fluent builder method to set the author property
     */
    public withAuthor(author_: GitHubId) {
        this._author = author_;
        return this;
    }

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

    /**
     * Fluent builder method to set the base property
     */
    public withBase(base_: Commit) {
        this._base = base_;
        return this;
    }

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

    /**
     * Fluent builder method to set the baseBranchName property
     */
    public withBaseBranchName(baseBranchName_: string) {
        this._baseBranchName = baseBranchName_;
        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 ` +
                `[PullRequest] 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;
    }

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

    /**
     * Fluent builder method to set the branch property
     */
    public withBranch(branch_: Branch) {
        this._branch = branch_;
        return this;
    }

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

    /**
     * Fluent builder method to set the branchName property
     */
    public withBranchName(branchName_: string) {
        this._branchName = branchName_;
        return this;
    }

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

    /**
     * Fluent builder method to add an element to the builds array
     */
    public addBuilds(...builds_: Build[]) {
        if (this._builds === undefined) {
            this._builds = [];
        }
        this._builds = this._builds.concat(builds_);
        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 ` +
                `[PullRequest] 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;
    }

    /**
     * comments - PullRequest -> 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 ` +
                `[PullRequest] 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;
    }

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

    /**
     * Fluent builder method to add an element to the commits array
     */
    public addCommits(...commits_: Commit[]) {
        if (this._commits === undefined) {
            this._commits = [];
        }
        this._commits = this._commits.concat(commits_);
        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 ` +
                `[PullRequest] 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;
    }

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

    /**
     * Fluent builder method to set the head property
     */
    public withHead(head_: Commit) {
        this._head = head_;
        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 ` +
                `[PullRequest] 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 - PullRequest -> 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 ` +
                `[PullRequest] 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 - PullRequest -> 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 ` +
                `[PullRequest] 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;
    }

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

    /**
     * Fluent builder method to set the mergeCommit property
     */
    public withMergeCommit(mergeCommit_: Commit) {
        this._mergeCommit = mergeCommit_;
        return this;
    }

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

    /**
     * Fluent builder method to set the merged property
     */
    public withMerged(merged_: boolean) {
        this._merged = merged_;
        return this;
    }

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

    /**
     * Fluent builder method to set the mergedAt property
     */
    public withMergedAt(mergedAt_: string) {
        this._mergedAt = mergedAt_;
        return this;
    }

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

    /**
     * Fluent builder method to set the merger property
     */
    public withMerger(merger_: GitHubId) {
        this._merger = merger_;
        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 ` +
                `[PullRequest] 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 ` +
                `[PullRequest] 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;
    }

    /**
     * repo - PullRequest -> 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 ` +
                `[PullRequest] 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;
    }

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

    /**
     * Fluent builder method to add an element to the reviewers array
     */
    public addReviewers(...reviewers_: GitHubId[]) {
        if (this._reviewers === undefined) {
            this._reviewers = [];
        }
        this._reviewers = this._reviewers.concat(reviewers_);
        return this;
    }

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

    /**
     * Fluent builder method to add an element to the reviews array
     */
    public addReviews(...reviews_: Review[]) {
        if (this._reviews === undefined) {
            this._reviews = [];
        }
        this._reviews = this._reviews.concat(reviews_);
        return this;
    }

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

    /**
     * Fluent builder method to set the state property
     */
    public withState(state_: string) {
        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 ` +
                `[PullRequest] 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 ` +
                `[PullRequest] 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 ` +
                `[PullRequest] 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;
    }

}
