"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
Object.defineProperty(exports, "__esModule", { value: true });
const core_1 = require("@angular/core");
const http_1 = require("@angular/http");
const material_1 = require("@angular/material");
const store_1 = require("@ngrx/store");
const BehaviorSubject_1 = require("rxjs/BehaviorSubject");
const Observable_1 = require("rxjs/Observable");
require("rxjs/add/observable/interval");
require("rxjs/add/operator/combineLatest");
require("rxjs/add/operator/publishReplay");
require("rxjs/add/operator/switchMap");
require("rxjs/add/operator/take");
require("rxjs/add/operator/takeUntil");
const env_1 = require("../util/env");
const report_issue_1 = require("../util/report-issue");
var State;
(function (State) {
    State[State["LoggingIn"] = 0] = "LoggingIn";
    State[State["Connecting"] = 1] = "Connecting";
    State[State["AwaitingGameClient"] = 2] = "AwaitingGameClient";
    State[State["NotifyMismatched"] = 3] = "NotifyMismatched";
})(State = exports.State || (exports.State = {}));
/**
 * The Launch Dialog prompts the user to log in, and connect to Interactive
 * for them. It calls back with connection details, or undefined if the dialog
 * was dismissed beforehand.
 */
let LaunchDialogComponent = class LaunchDialogComponent {
    constructor(http, dialogRef, snackRef, store) {
        this.http = http;
        this.dialogRef = dialogRef;
        this.snackRef = snackRef;
        this.store = store;
        /**
         * Exposed State enum for the template to consume.
         */
        this.State = State; // tslint:disable-line
        /**
         * Curre state of the component.
         */
        this.state = new BehaviorSubject_1.BehaviorSubject(State.LoggingIn);
        /**
         * Dots used to subtly indicate progress.
         */
        this.dots = Observable_1.Observable.interval(250)
            .map(x => {
            let n = '.';
            while (n.length < x % 3 + 1) {
                n += '.';
            }
            return n;
        })
            .publishReplay(1)
            .refCount();
    }
    onLoggedIn() {
        this.state.next(State.Connecting);
        this.connect();
    }
    /**
     * Closes the dialog with the data to connect to Interactive.
     */
    acceptConnect() {
        this.dialogRef.close(this.loadedData);
    }
    /**
     * Cancels connecting and closes the dialog.
     */
    cancelConnect() {
        this.dialogRef.close();
    }
    /**
     * Attempts to create a connection to Interactive. Closes the dialog
     * when it successfully does so.
     */
    connect() {
        this.store
            .select(s => s.connect.channelOverride)
            .take(1)
            .switchMap(channelID => this.http.get(env_1.apiUrl('connect-participant'), { params: { channelID } }))
            .combineLatest(this.store.map(s => s.sync.interactiveVersion))
            .subscribe(([res, version]) => {
            const data = res.json();
            this.loadedData = data;
            // If the game client is not connected, wait for it to do so.
            if (!data.address) {
                this.waitForConnect();
                return;
            }
            // Prompt the user is the game version the client is connecting
            // with is different than the one they have linked.
            if (version && version.id !== data.version.id) {
                this.versionMismatch = {
                    intendedVersion: version,
                    actualVersion: data.version,
                };
                this.state.next(State.NotifyMismatched);
                return;
            }
            this.acceptConnect();
        }, (err) => {
            switch (err.status) {
                case 409:
                    this.waitForConnect();
                    break;
                default:
                    this.snackRef
                        .open('An unknown error occurred', 'Report', { duration: 5000 })
                        .onAction()
                        .subscribe(() => {
                        report_issue_1.reportHttpError('Unknown error in launch dialog', err);
                    });
                    this.cancelConnect();
                    break;
            }
        });
    }
    /**
     * Waits for the game client connect, polling occasionally.
     */
    waitForConnect() {
        this.state.next(State.AwaitingGameClient);
        Observable_1.Observable.interval(5000)
            .take(1)
            .takeUntil(this.dialogRef.afterClosed())
            .subscribe(() => {
            this.connect();
        });
    }
};
LaunchDialogComponent = __decorate([
    core_1.Component({
        selector: 'launch-dialog',
        templateUrl: './launch-dialog.component.html',
        styleUrls: ['../dialog.scss', './launch-dialog.component.scss'],
        changeDetection: core_1.ChangeDetectionStrategy.OnPush,
    }),
    __metadata("design:paramtypes", [http_1.Http,
        material_1.MatDialogRef,
        material_1.MatSnackBar,
        store_1.Store])
], LaunchDialogComponent);
exports.LaunchDialogComponent = LaunchDialogComponent;
