import { ICommandService, IImageIoService, Injector, IUniverInstanceService, LifecycleService, Univer } from '@univerjs/core';
import { FUniver } from '@univerjs/core/facade';

import { JnpfFacadeSheetsCell } from '../facade/f-sheet-cell';
import { JnpfFacadeSheetsCellImage } from '../facade/f-sheet-cell-image';
import { JnpfFacadeSheetsFloatDom } from '../facade/f-sheet-float-dom';
import { JnpfFacadeSheetsPrint } from '../facade/f-sheet-print';
import { JnpfFacadeSheetsRange } from '../facade/f-sheet-range';
import { JnpfSheetsCellImageService } from '../services/sheet-cell-image.service';
import { JnpfSheetsCellService } from '../services/sheet-cell.service';
import { JnpfSheetsFloatDomService } from '../services/sheet-float-dom.service';
import { JnpfSheetsFloatEchartService } from '../services/sheet-float-echart.service';
import { JnpfSheetsFloatImageService } from '../services/sheet-float-image.service';
import { JnpfSheetImageIoImplService } from '../services/sheet-image-io-impl.service';
import { JnpfSheetsPrintService } from '../services/sheet-print.service';
import { JnpfSheetsRangeService } from '../services/sheet-range.service';
import { JnpfFacadeSheetsFloatEchart } from './f-sheet-float-echart';
import { JnpfFacadeSheetsFloatImage } from './f-sheet-float-image';

import '@univerjs/sheets/facade';
import '@univerjs/ui/facade';
import '@univerjs/docs-ui/facade';
import '@univerjs/sheets-ui/facade';
import '@univerjs/sheets-filter/facade';
import '@univerjs/engine-formula/facade';
import '@univerjs/sheets-formula/facade';
import '@univerjs/sheets-data-validation/facade';
import '@univerjs/sheets-hyper-link/facade';
import '@univerjs/sheets-hyper-link-ui/facade';
import '@univerjs/watermark/facade';
import '@univerjs/sheets-thread-comment/facade';
import '@univerjs/sheets-crosshair-highlight/facade';

export class JnpfFUniver extends FUniver {
  constructor(injector: Injector, commandService: ICommandService, instanceService: IUniverInstanceService) {
    const lifecycleService = injector.get<LifecycleService>(LifecycleService);
    if (!lifecycleService) {
      throw new Error('LifecycleService 未正确注入');
    }

    super(injector, commandService, instanceService, lifecycleService);
  }

  static newAPI(wrapped: Injector | Univer): JnpfFUniver {
    const injector = wrapped instanceof Univer ? wrapped.__getInjector() : wrapped;
    const commandService = injector.get<ICommandService>(ICommandService);
    const instanceService = injector.get<IUniverInstanceService>(IUniverInstanceService);

    if (!commandService || !instanceService) {
      throw new Error('注入ICommandService或IUniverInstanceService发生错误');
    }

    return new JnpfFUniver(injector, commandService, instanceService);
  }

  getInjector() {
    return this._injector;
  }

  getSheetsCell(): JnpfFacadeSheetsCell | null {
    const jnpfSheetsCellService = this._injector.get(JnpfSheetsCellService);

    if (!jnpfSheetsCellService) {
      return null;
    }

    return this._injector.createInstance(JnpfFacadeSheetsCell, jnpfSheetsCellService);
  }

  getSheetsCellImage(): JnpfFacadeSheetsCellImage | null {
    const jnpfSheetsCellImageService = this._injector.get(JnpfSheetsCellImageService);

    if (!jnpfSheetsCellImageService) {
      return null;
    }

    return this._injector.createInstance(JnpfFacadeSheetsCellImage, jnpfSheetsCellImageService);
  }

  getSheetsFloatDom(): JnpfFacadeSheetsFloatDom | null {
    const jnpfSheetsFloatDomService = this._injector.get(JnpfSheetsFloatDomService);

    if (!jnpfSheetsFloatDomService) {
      return null;
    }

    return this._injector.createInstance(JnpfFacadeSheetsFloatDom, jnpfSheetsFloatDomService);
  }

  getSheetsFloatEchart(): JnpfFacadeSheetsFloatEchart | null {
    const jnpfSheetsFloatEchartService = this._injector.get(JnpfSheetsFloatEchartService);

    if (!jnpfSheetsFloatEchartService) {
      return null;
    }

    return this._injector.createInstance(JnpfFacadeSheetsFloatEchart, jnpfSheetsFloatEchartService);
  }

  getSheetsFloatImage(): JnpfFacadeSheetsFloatImage | null {
    const jnpfSheetsFloatImageService = this._injector.get(JnpfSheetsFloatImageService);
    const jnpfSheetImageIoImplService = this._injector.get(IImageIoService);
    if (!jnpfSheetImageIoImplService) {
      return null;
    }
    if (!jnpfSheetsFloatImageService) {
      return null;
    }

    return this._injector.createInstance(JnpfFacadeSheetsFloatImage, jnpfSheetsFloatImageService, jnpfSheetImageIoImplService as JnpfSheetImageIoImplService);
  }

  getSheetsPrint(): JnpfFacadeSheetsPrint | null {
    const jnpfSheetsPrintService = this._injector.get(JnpfSheetsPrintService);

    if (!jnpfSheetsPrintService) {
      return null;
    }

    return this._injector.createInstance(JnpfFacadeSheetsPrint, jnpfSheetsPrintService);
  }

  getSheetsRange(): JnpfFacadeSheetsRange | null {
    const jnpfSheetsRangeService = this._injector.get(JnpfSheetsRangeService);

    if (!jnpfSheetsRangeService) {
      return null;
    }

    return this._injector.createInstance(JnpfFacadeSheetsRange, jnpfSheetsRangeService);
  }
}
