class ClientbaseMetadata {

  _instance;  
  _promises = {};
  dataTablesSource;
  dataTables;
  fields;
  groups;
  users;

  fieldTypes = {

    NUMBER: 1,               // числовое
    DATE: 2,               // дата
    TEXT: 3,               // текст
    LIST: 4,               // список
    LINK: 5,               // связь
    FILE: 6,               // файл
    USER: 7,               // пользователь
    IMAGE: 9,               // изображение
    GROUP: 14,              // группа
    //  Системные типы полей КБ
    ID: 10,              // id
    USER_ID: 11,              // Кто добавил / user_id
    ADD_TIME: 12,              // Время добавления / add_time
    STATUS: 13 

  };
  
  
  constructor() {

        if (ClientbaseMetadata._instance) {
          return ClientbaseMetadata._instance;
        }
    
        ClientbaseMetadata._instance = this;

  }

  //private
  //Загружаем данные из API по URL
  async api(url, method="GET", body=null) {

      url = "./api/dev/" + url;

      let response = await fetch(url, {
          method: method,
          credentials: "include",
          headers: {                   
              'X-Auth-Token' : window.x_auth_token || null,
              'Content-Type': 'application/vnd.api+json'
          },
          body: body
      });
      
      response = await response.json(); 
      return response; 

  }

  //private
  //Получаем и сохраняем данные
  //dataProcessor - функция обработки/сохранения данных  
  async loadData(url, dataProcessor) {

    if (!this._promises[url]) {

      var self = this;

      this._promises[url] = new Promise(async function(resolve, reject) {

        let data = await self.api(url);

        resolve(dataProcessor(data));

      });

    }

    return this._promises[url];

  }  

  //Получить список таблиц
  async getDataTables(force=false) {

    var result = '';

    if (this.dataTables && !force) {

      result = this.dataTables;

    } else {

      self = this;

      result = this.loadData("table", function(result) {

        self.dataTablesSource = result.data;

        self.dataTables = {};

        self.dataTablesSource.forEach(function(item) {

          this.dataTables[item.id] = item.attributes.table_name;
  
        }, self);  

        return self.dataTables;

      });

    }

    return result;

  }

  //Получить список полей таблицы с возможностью фильтра по типу поля
  //fieldType = 0 - все типы полей
  async getFields(tableId, fieldType=0, force=false) {

    if (!this.fields) {

      this.fields = {};

    }

    if (typeof fieldType === "string") {

      let upFieldType = fieldType.toUpperCase();

      if (this.fieldTypes[upFieldType]) {

        fieldType = this.fieldTypes[upFieldType];

      }

    }

    var result = '';

    if (this.fields[tableId] && !force) {

      result = this.fields[tableId][fieldType];

    } else {

      let url = "table/" + tableId + "?include=fields&fieldType=" + fieldType;

      self = this;

      result = this.loadData(url, function(result) {

        self.fields[tableId] = {};
        self.fields[tableId][0] = {};
          
        result.included.forEach(function (item) {

          let id = item.id;
          let type = item.attributes.field_type;
          let name = item.attributes.field_name;

          this.fields[tableId][0][id] = name;

          if (!this.fields[tableId][type]) {

            this.fields[tableId][type] = {};

          }

          this.fields[tableId][type][id] = name;

        }, self);
        
        return self.fields[tableId][fieldType];

      });

    }

    return result;

  }

  async getGroups(force=false) {

    var result = '';

    if (this.groups && !force) {

      result = this.groups;

    } else {

      self = this;

      result = this.loadData("group", function(result) {

        self.groups = {};

        result.data.forEach(function(item) {

          this.groups[item.id] = item.attributes.name;
  
        }, self);  

        return self.groups;

      });

    }

    return result;


  }



}

export const cbMetaData = new ClientbaseMetadata();
