/*
 * Copyright (C) 2022 Savoir-faire Linux Inc.
 *
 * 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
 * <https://www.gnu.org/licenses/>.
 */

/* eslint-disable no-undef */
// TODO: This hides eslint errors for this file. This should be removed once this file is cleaned up.

import { PromiseExecutor } from 'jami-web-common';

interface AuthManagerState {
  initialized: boolean;
  authenticated: boolean;
  setupComplete: boolean;
  error: boolean;
}

interface AuthManagerTask extends PromiseExecutor<Response> {
  url: string;
  init?: RequestInit;
}

interface InitData {
  loggedin?: true;
  username?: string;
  type?: string;
  setupComplete?: boolean;
}

type OnAuthChanged = (auth: AuthManagerState) => void;

class AuthManager {
  private authenticating: boolean;
  private readonly _state: AuthManagerState;
  private tasks: AuthManagerTask[];
  private onAuthChanged: OnAuthChanged | undefined;

  constructor() {
    console.log('AuthManager()');
    this.authenticating = false;

    this._state = {
      initialized: false,
      authenticated: true,
      setupComplete: true,
      error: false,
    };

    this.tasks = [];
    this.onAuthChanged = undefined;
  }

  isAuthenticated() {
    return this._state.authenticated;
  }

  getState() {
    return this._state;
  }

  setInitData(data: InitData) {
    this.authenticating = false;
    this._state.initialized = true;
    if (data.username) {
      Object.assign(this._state, {
        authenticated: true,
        setupComplete: true,
        error: false,
        user: { username: data.username, type: data.type },
      });
    } else {
      Object.assign(this._state, {
        authenticated: false,
        setupComplete: data.setupComplete ?? true,
        error: false,
      });
    }
    console.log('Init ended');
    /*if (this.onAuthChanged)
            this.onAuthChanged(this._state)*/
  }

  init(cb: OnAuthChanged) {
    this.onAuthChanged = cb;
    if (this._state.initialized || this.authenticating) return;
    /*if (initData) {
            console.log("Using static initData")
            this.setInitData(initData)
            return
        }*/
    this.authenticating = true;
    fetch('/auth')
      .then(async (response) => {
        this.authenticating = false;
        this._state.initialized = true;
        if (response.status === 200) {
          this.setInitData(await response.json());
        } else if (response.status === 401) {
          this.setInitData(await response.json());
        } else {
          this._state.error = true;
          if (this.onAuthChanged) this.onAuthChanged(this._state);
        }
      })
      .catch((e) => {
        this.authenticating = false;
        console.log(e);
      });
  }

  deinit() {
    console.log('Deinit');
    this.onAuthChanged = undefined;
  }

  async setup(password: string) {
    if (this.authenticating || this._state.setupComplete) return;
    console.log('Starting setup');
    this.authenticating = true;
    const response = await fetch(`/setup`, {
      method: 'POST',
      headers: {
        Accept: 'application/json',
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ password }),
    });
    console.log(response);
    if (response.ok) {
      console.log('Success, going home');
      //navigate('/')
    }

    this.authenticating = false;
    this._state.setupComplete = true;
    if (this.onAuthChanged) this.onAuthChanged(this._state);
    return response.ok;
  }

  authenticate(username: string, password: string) {
    if (this.authenticating) return;
    console.log('Starting authentication');
    this.authenticating = true;
    fetch(`/auth/local?username=${encodeURIComponent(username)}&password=${encodeURIComponent(password)}`, {
      method: 'POST',
    })
      .then((response) => {
        console.log(response);
        this.authenticating = false;
        this._state.authenticated = response.ok && response.status === 200;
        if (this.onAuthChanged) this.onAuthChanged(this._state);
        while (true) {
          const task = this.tasks.shift();
          if (!task) {
            break;
          }
          if (this._state.authenticated) {
            fetch(task.url, task.init)
              .then((res) => task.resolve(res))
              .catch((e) => console.log('Error executing pending task: ' + e));
          } else {
            task.reject(new Error('Authentication failed'));
          }
        }
      })
      .catch((e) => {
        this.authenticating = false;
        console.log(e);
      });
  }

  disconnect() {
    console.log('Disconnect');
    this._state.authenticated = false;
    if (this.onAuthChanged) this.onAuthChanged(this._state);
  }

  fetch(url: string, init?: RequestInit): Promise<Response> {
    console.log(`fetch ${url}`);
    if (!this._state.authenticated) {
      if (!init || !init.method || init.method === 'GET') {
        return new Promise<Response>((resolve, reject) => this.tasks.push({ url, init, resolve, reject }));
      } else {
        return new Promise<Response>((resolve, reject) => reject('Not authenticated'));
      }
    }
    return fetch(url, init).then((response) => {
      if (response.status === 401) {
        this.disconnect();
        return this.fetch(url, init);
      }
      return response;
    });
  }
}

export default new AuthManager();
