import { HttpClient } from '@angular/common/http'
import { Injectable } from '@angular/core'
import { Observable } from 'rxjs'
import {
  SASjsApiDriveFileTree,
  SASjsApiTree
} from '../models/sasjs-api/SASjsApiDriveFileTree.model'
import { SASjsApiDriveFolderContents } from '../models/sasjs-api/SASjsApiDriveFolderContents.model'
import { SASjsApiServerInfo } from '../models/sasjs-api/SASjsApiServerInfo.model'
import { AppStoreService } from './app-store.service'

@Injectable({
  providedIn: 'root'
})
export class SasjsService {
  private url: string = ''
  private driveUrl: string = ''

  private httpOptions = {
    withCredentials: true
  }

  constructor(
    private http: HttpClient,
    private appStoreService: AppStoreService
  ) {}

  /**
   * This function is replacing the constructor.
   * The reason for this is timing issues, other services eg. sas.service, app-store.service
   * must be initialized before this bit of code is executed.
   * This function is being called by `sas.service`
   */
  setup() {
    const adapterConfig = this.appStoreService.getDcAdapterSettings()

    this.url = `${adapterConfig?.serverUrl || ''}/SASjsApi`
    this.driveUrl = `${this.url}/drive`
  }

  /**
   *
   * @returns Sasjs/server information
   */
  getServerInfo(): Observable<SASjsApiServerInfo> {
    return this.http.get<SASjsApiServerInfo>(`${this.url}/info`)
  }

  /**
   * Gets file contents on a given path
   * @param filePath path to the file
   */
  getFileFromDrive(filePath: string) {
    return this.http.get(
      `${this.driveUrl}/file/?_filePath=${filePath}`,
      this.httpOptions
    )
  }

  /**
   * Gets folder contents on a given path
   * @param folderPath path to the folder
   * @returns
   */
  getFolderContentsFromDrive(
    folderPath: string
  ): Observable<SASjsApiDriveFolderContents> {
    return this.http.get<SASjsApiDriveFolderContents>(
      `${this.driveUrl}/folder?_folderPath=${folderPath}`,
      this.httpOptions
    )
  }

  getFileTreeFromDrive(): Observable<SASjsApiDriveFileTree> {
    return this.http.get<SASjsApiDriveFileTree>(
      `${this.driveUrl}/filetree`,
      this.httpOptions
    )
  }

  getFileFromFileTree(filePath: string) {
    return new Promise((resolve, reject) => {
      this.getFileTreeFromDrive().subscribe(
        (fileTree: SASjsApiDriveFileTree) => {
          const tree = fileTree.tree

          const found = this.findInTree(tree, filePath)

          resolve(found)
        }
      )
    })
  }

  private findInTree(tree: SASjsApiTree, filePath: string) {
    if (tree.relativePath === filePath) {
      return tree
    }

    for (let branch of tree.children) {
      const found: any = this.findInTree(branch, filePath)

      if (found) {
        return found
      }
    }
  }
}
