import request from '@/utils/request';
import { PriceAccuracy, computedTime, parseCoinAmount } from './tool';
/**
 * @key Server ding字段 supported_resolutions
 */
// 1min, 5min, 15min, 30min, 60min, 4hour, 1day, 1mon, 1week, 1year
export const intervalMap = {
  '1min': '1',
  '5min': '5',
  '15min': '15',
  '30min': '30',
  '60min': '60',
  '4hour': '240',
  '1day': 'D',
  '1week': 'W',
  '1mon': 'M',
};
/** trading-view 的時間區間 */
export const supportedResolutions = [
  '1',
  '5',
  '15',
  '30',
  '60',
  '240',
  'D',
  'W',
  'M',
];

export class DataFeed {
  private symbolInfo: any;
  private subscribers: any[] = [];
  private interval = null;
  private resolution = '15';
  private currentPath = '';
  // 每个时间段都要给5次重试次数
  private RetryTime = {
    r1: 0,
    r5: 0,
    r15: 0,
    r60: 0,
    r240: 0,
    r1D: 0,
  };
  private KPirce = null;
  constructor(symbolInfo: any, timeInterval = 1000) {
    this.currentPath = symbolInfo.currentPath;
    this.KPirce = symbolInfo.KPirce;
    // 将传过来的多余参数剔除
    delete symbolInfo.KPirce;
    delete symbolInfo.currentPath;
    this.symbolInfo = symbolInfo;
    this.intervalGetBars(symbolInfo.ticker, timeInterval);
  }
  public onReady(onGameLoad: any) {
    new Promise((resolve) => {
      resolve(void 0);
    }).then(() => {
      onGameLoad({
        supported_resolutions: supportedResolutions,
      });
    });
  }
  public searchSymbols() {}
  public resolveSymbol(
    symbolName: any,
    onSymbolResolvedCallback: any,
    onResolveErrorCallback: any
  ) {
    new Promise((resolve) => {
      resolve(void 0);
    }).then(() => {
      let PriceNum = 10000000000;
      PriceNum = PriceAccuracy(this.KPirce);
      onSymbolResolvedCallback({
        session: '24x7',
        timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
        supported_resolutions: supportedResolutions,
        has_intraday: true,
        has_daily: true,
        // has_no_volume: true,
        minmov: 1,
        // minmove2:0,
        // 最多支持16位小数
        pricescale: PriceNum,
        format: 'price',
        ...this.symbolInfo,
      });
    });
  }
  /**
   * 订阅K线数据。图表库将调用onRealtimeCallback方法以更新实时数据
   */
  public subscribeBars(
    symbolInfo: any,
    resolution: string,
    onRealtimeCallback: any,
    subscriberUID: string,
    onResetCacheNeededCallback: () => void
  ) {
    if (this.subscribers[subscriberUID]) {
      return;
    }
    this.resolution = resolution;
    this.subscribers[subscriberUID] = {
      lastBarTime: null,
      listener: onRealtimeCallback,
      resolution: resolution,
      symbolInfo: symbolInfo,
    };
  }

  /**
   * 取消订阅K线数据
   */
  public unsubscribeBars(subscriberUID: string) {
    if (!this.subscribers[subscriberUID]) {
      return;
    }
    delete this.subscribers[subscriberUID];
  }

  public updateKLine(bar: any) {
    for (const listenerGuid in this.subscribers) {
      const subscriptionRecord = this.subscribers[listenerGuid];
      if (
        subscriptionRecord.lastBarTime !== null &&
        bar.time < subscriptionRecord.lastBarTime
      ) {
        continue;
      }
      subscriptionRecord.lastBarTime = bar.time;
      subscriptionRecord.listener(bar);
    }
  }
  public async getBars(
    symbolInfo: any,
    resolution: any,
    periodParams: any,
    onHistoryCallback: any,
    onErrorCallback: any
  ) {
    try {
      let params = {
        ...periodParams,
        resolution,
        symbol: symbolInfo.ticker,
      };
      params.from = params.from * 1000;
      params.to = params.to * 1000;
      // 是否第一次請求歷史數據
      if (periodParams.firstDataRequest) {
        params.to = Date.now();
      }
      const res = request
        .get(`/v1/${this.currentPath}/chart/bars`, {
          params,
        })
        .then((res: any) => {
          let result = {
            bars: [],
            meta: { noData: false },
          };
          if (
            res.list &&
            res.list.length > 0 &&
            this.RetryTime[`r${resolution}`] < 5
          ) {
            result.meta.noData = false;
            result.bars = res.list.map((item: any) => {
              return {
                time: item.ts,
                open: item.open,
                high: item.high,
                low: item.low,
                close: item.close,
                volume: item.volume,
              };
            });
          } else {
            if (this.RetryTime[`r${resolution}`] < 5) {
              this.RetryTime[`r${resolution}`] += 1;
            } else {
              result.meta.noData = true;
            }
          }
          onHistoryCallback(result.bars, result.meta);
        });
    } catch (error) {
      onHistoryCallback({
        bars: [],
        meta: { noData: true },
      });
    }
  }
  public intervalGetBars(symbol: any, timeInterval: any) {
    this.interval = setInterval(() => {
      let from = computedTime(this.resolution);
      let current = new Date().getTime();
      let params = {
        resolution: this.resolution,
        to: current,
        // from: current - timeInterval,
        from: from ? from : current - timeInterval,
        // from: current - 5000,
        symbol: symbol,
        firstDataRequest: false,
        countBack: 2,
      };
      request
        .get(`/v1/${this.currentPath}/chart/bars`, {
          params: params,
        })
        .then((res: any) => {
          if (res && res.list) {
            res.list.forEach((item: any) => {
              this.updateKLine({
                time: item.ts,
                open: item.open,
                high: item.high,
                low: item.low,
                close: item.close,
                volume: item.volume,
              });
            });
          }
        });
    }, 5000);
  }
  public clearIntervalGetBars() {
    clearInterval(this.interval);
  }
}
export class Widget {
  private options: any;
  public widget = null;
  constructor(options = {}) {
    const mode = useCurTheme();
    // 获取当前语言
    let CurLanguage = 'zh';
    if (navigator.language === 'zh-CN' || navigator.language === 'zh-TW') {
      CurLanguage = 'zh';
    } else {
      CurLanguage = 'en';
    }
    this.options = {
      // debug: true,
      library_path: '/charting_library/',
      // 主题
      // theme: 'light',
      theme: mode.value,
      locale: CurLanguage, //测试先用en
      autosize: !0,
      container: 'tv_chart_container',
      timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
      interval: '15',
      customFormatters: {
        priceFormatterFactory: this.CustomPriceScaleMode,
      },
      favorites: {
        intervals: ['1', '5', '15', '60', '240', 'D', 'W', 'M'],
        chartTypes: ['Candles', 'Line'],
      },
      // enabled_features: ['study_templates'],
      disabled_features: [
        'header_symbol_search',
        'header_compare',
        'header_saveload',
        'header_fullscreen_button',
        // 禁用本地存储功能
        // 'use_localstorage_for_settings',
        'save_chart_properties_to_local_storage',
      ],
      overrides: {
        // 默认展示的图表
        'mainSeriesProperties.style': 1,
        'mainSeriesProperties.highLowAvgPrice.highLowPriceLinesVisible': true, //高低线值
        'mainSeriesProperties.highLowAvgPrice.highLowPriceLabelsVisible': true, //高低线名称
        'mainSeriesProperties.highLowAvgPrice.averageClosePriceLineVisible':
          true, //均线
        'mainSeriesProperties.highLowAvgPrice.averageClosePriceLabelVisible':
          true, //均线
      },
      // custom_css_url: '/src/style/tradingview.less',
      ...options,
    };
    this.initWidget();
  }
  public initWidget() {
    this.widget = window.tvWidget = new TradingView.widget(this.options);
  }
  public CustomPriceScaleMode(this: any, symbolInfo: any, minTick: string) {
    let currentPrice = useCurrentKLinePrice();
    let maxLength = 0;
    return {
      format(price: number) {
        if (price >= 0.1) {
          // 保留四位小数即可
          return price.toFixed(4);
        }
        let newprice = '';
        // 统一价格小数点位数
        let priceNum = PriceAccuracy(currentPrice.value);
        if (priceNum > maxLength) {
          maxLength = priceNum;
        }
        // 获取0的个数
        let re = eval('/0/g');
        let test = (maxLength + '').match(re);
        if (test && test.length) {
          // 这里将价格精度改为同样的长度
          newprice = price.toFixed(test.length);
          //
          if (parseFloat(newprice) > 0.0001) {
            return newprice;
          }
          newprice = parseCoinAmount(newprice);
          return newprice;
        }

        newprice = parseCoinAmount(price);
        return newprice;
      },
    };
  }
}
