import { KnapsackDesignToken } from '@knapsack/core/types';
import { KsCloudConfig, KnapsackFile } from '@knapsack/core';
import { KsServerPlugin } from './plugins';
import {
  KnapsackPattern,
  KnapsackPatternTemplate,
  KnapsackTemplateDemo,
  KsTemplateSpec,
} from './patterns';

type Patterns = import('../server/patterns').Patterns;

export interface KnapsackTemplateRendererResults {
  ok: boolean;
  html: string;
  usage?: string;
  templateLanguage?: string;
  message?: string;
}

export interface KsRenderResults extends KnapsackTemplateRendererResults {
  wrappedHtml: string;
  /** md5 hash of `demo` used */
  dataId: string;
}

export interface KsTemplateUrls {
  /**
   * Is not in iframe, is wrapped html
   */
  external: string;
  /**
   * Is in iframe, is wrapped html
   */
  iframeSrc: string;
}

export interface KsTemplateRenderedMeta extends KsRenderResults {
  urls: KsTemplateUrls;
}

export interface GetHeadParams {
  cssUrls?: string[];
  headJsUrls?: string[];
  inlineHead?: string;
  isInIframe?: boolean;
}
export interface GetFootParams {
  jsUrls?: string[];
  inlineJs?: string;
  inlineCss?: string;
  inlineFoot?: string;
  isInIframe?: boolean;
}

export interface TemplateRendererMeta {
  id: string;
  title: string;
  iconSvg?: string;
  version?: string;
  aliasTitle?: string;
  aliasDescription?: string;
  aliasUse: 'off' | 'optional' | 'required';
  syntaxHighlightingLanguage?: string;
}

export type KsTemplateRendererWrapHtmlParams = {
  html: string;
} & GetHeadParams &
  GetFootParams;

export interface KnapsackTemplateRendererBase {
  id: string;
  /**
   * Used for syntax highlighting
   */
  language?: string;
  build?: (opt: { templatePaths: string[] }) => Promise<void>;
  watch?: (opt: { templatePaths: string[] }) => Promise<void>;
  init?: (opt: {
    config: KnapsackConfig;
    patterns: Patterns;
    cacheDir: string;
  }) => Promise<void>;
  wrapHtml: (opt: KsTemplateRendererWrapHtmlParams) => string;
  getHead: (opt: GetHeadParams) => string;
  getFoot: (opt: GetFootParams) => string;
  onChange: (opt: { path: string }) => void;
  onAdd: (opt: { path: string }) => void;
  onRemove: (opt: { path: string }) => void;
  formatCode: (code: string) => string;
  inferSpec?: ({
    template: KnapsackPatternTemplate,
    templatePath: string,
  }) => Promise<KsTemplateSpec | false>;
  getTemplateMeta?: (opt: {
    pattern: KnapsackPattern;
    template: KnapsackPatternTemplate;
  }) => Promise<KnapsackFile[]>;
  /**
   * The result of all the `getTemplateMeta` runs aggregated together
   * @see {KnapsackTemplateRendererBase['getTemplateMeta']}
   * @see getTemplateMeta
   * @see {getTemplateMeta}
   */
  alterTemplateMetaFiles?: (opt: {
    files: KnapsackFile[];
    metaDir: string;
  }) => Promise<KnapsackFile[]>;
}

export interface KnapsackRenderParams {
  template: KnapsackPatternTemplate;
  pattern: KnapsackPattern;
  demo?: KnapsackTemplateDemo;
  // data?: KnapsackTemplateData;
  patternManifest: Patterns;
}

export type KnapsackRenderFunc = (
  opt: KnapsackRenderParams,
) => Promise<KnapsackTemplateRendererResults>;

export interface KnapsackTemplateRenderer extends KnapsackTemplateRendererBase {
  render: KnapsackRenderFunc;
  // render: (opt: {
  //   template: KnapsackPatternTemplate;
  //   pattern: KnapsackPattern;
  //   demo?: KnapsackTemplateDemo;
  //   data?: KnapsackTemplateData;
  //   patternManifest: Patterns;
  // }) => Promise<KnapsackTemplateRendererResults>;
  // renderString?: (
  //   template: string,
  //   data?: KnapsackTemplateData,
  // ) => Promise<KnapsackTemplateRendererResults>;
  getUsage: (opt: KnapsackRenderParams) => Promise<string>;
  getMeta: () => TemplateRendererMeta;
  // getUsage?: (opt: {
  //   patternId: string;
  //   template: KnapsackPatternTemplate;
  //   data?: KnapsackTemplateData;
  //   demo?: KnapsackTemplateDemo;
  //   patternManifest: Patterns;
  // }) => Promise<string>;
}

export interface KnapsackConfig {
  /** Output of knapsack build directory */
  dist: string;
  /** Knapsack data including site meta and page builder */
  data: string;
  /** Hosted by knapsack server. Place compiled Design System css and js as well as images and other assets needed by knapsack */
  public: string;
  // assetSets: KnapsackAssetSetsConfig[];
  templateRenderers: KnapsackTemplateRenderer[];
  designTokens: {
    createCodeSnippet?: (token: KnapsackDesignToken) => string;
    data: {
      tokens: KnapsackDesignToken[];
    };
  };
  plugins?: KsServerPlugin<any>[];
  version?: string;
  cloud?: KsCloudConfig;
}
