// TODO return promises instead of inner await

import { IndexInterface, DocumentInterface } from "./type.js";
import { create_object, is_string } from "./common.js";

async function lazyExport(callback, self, key, index_doc, index, data){
  // Run the callback on the given data
  const res = callback(key, JSON.stringify(data));
  // If the callback gives a promise, then wait on that
  if (res && res["then"]) { await res; }

  // Recurse to export the next property
  return await self.export(callback, self, key, index_doc, index + 1);
}

/**
 * @this IndexInterface
 */

export async function exportIndex(callback, self, field, index_doc, index){

    let key, data;

    switch(index || (index = 0)){

        case 0:

            key = "reg";

            // fastupdate isn't supported by export

            if(this.fastupdate){

                data = create_object();

                for(let key in this.register){

                    data[key] = 1;
                }
            }
            else{

                data = this.register;
            }

            break;

        case 1:

            key = "cfg";
            data = {
                "doc": 0,
                "opt": this.optimize ? 1 : 0
            };

            break;

        case 2:

            key = "map";
            data = this.map;
            break;

        case 3:

            key = "ctx";
            data = this.ctx;
            break;

        default:

            // If there are no properties remaining to export, then return an empty promise with
            // 'true'
            return true;
    }

    return await lazyExport(callback, self || this, field ? field + "." + key : key, index_doc, index, data);
}

/**
 * @this IndexInterface
 */

export function importIndex(key, data){

    if(!data){

        return;
    }

    if(is_string(data)){

        data = JSON.parse(data);
    }

    switch(key){

        case "cfg":

            this.optimize = !!data["opt"];
            break;

        case "reg":

            // fastupdate isn't supported by import

            this.fastupdate = false;
            this.register = data;
            break;

        case "map":

            this.map = data;
            break;

        case "ctx":

            this.ctx = data;
            break;
    }
}

/**
 * @this DocumentInterface
 */

export async function exportDocument(callback, self, field, index_doc, index){

    index || (index = 0);
    index_doc || (index_doc = 0);

    if(index_doc < this.field.length){

        const field = this.field[index_doc];
        const idx = this.index[field];

        self = this;


      if(!(await idx.export(callback, self, index ? field/*.replace(":", "-")*/ : "", index_doc, index++))){

        index_doc++;
        index = 1;

        await self.export(callback, self, field, index_doc, index);
      }

      return true;
    }
    else{

        let key, data;

        switch(index){

            case 1:

                key = "tag";
                data = this.tagindex;
                break;

            case 2:

                key = "store";
                data = this.store;
                break;

            // case 3:
            //
            //     key = "reg";
            //     data = this.register;
            //     break;

            default:

                return true;
        }

        return await lazyExport(callback, this, key, index_doc, index, data);
    }
}

/**
 * @this DocumentInterface
 */

export function importDocument(key, data){

    if(!data){

        return;
    }

    if(is_string(data)){

        data = JSON.parse(data);
    }

    switch(key){

        case "tag":

            this.tagindex = data;
            break;

        case "reg":

            // fastupdate isn't supported by import

            this.fastupdate = false;
            this.register = data;

            for(let i = 0, index; i < this.field.length; i++){

                index = this.index[this.field[i]];
                index.register = data;
                index.fastupdate = false;
            }

            break;

        case "store":

            this.store = data;
            break;

        default:

            key = key.split(".");
            const field = key[0];
            key = key[1];

            if(field && key){

                this.index[field].import(key, data);
            }
    }
}

@@ -161,22 +161,16 @@
 n.js%22;%0A%0A
-async 
 function
@@ -170,26 +170,21 @@
 unction 
-lazyExport
+async
 (callbac
@@ -226,48 +226,43 @@
 a)%7B%0A
+%0A
   
-// Run the callback on the given data%0A
+  setTimeout(function()%7B%0A%0A      
   co
@@ -312,69 +312,60 @@
 ));%0A
+%0A
   
-// If the callback gives a promise, then wait on that%0A
+      // await isn't supported by ES5%0A%0A      
   if
- 
 (res
@@ -384,80 +384,171 @@
 n%22%5D)
- %7B await res; %7D%0A%0A  // Recurse to export the next property%0A  return await
+%7B%0A%0A            res%5B%22then%22%5D(function()%7B%0A%0A                self.export(callback, self, key, index_doc, index + 1);%0A            %7D)%0A        %7D%0A        else%7B%0A%0A           
  sel
@@ -600,16 +600,34 @@
 x + 1);%0A
+        %7D%0A    %7D);%0A
 %7D%0A%0A/**%0A 
@@ -653,38 +653,32 @@
 ace%0A */%0A%0Aexport 
-async 
 function exportI
@@ -1544,174 +1544,32 @@
     
-// If there are no properties remaining to export, then return an empty promise with%0A            // 'true'%0A            return true;%0A    %7D%0A%0A    return await lazyExport
+return;%0A    %7D%0A%0A    async
 (cal
@@ -1646,16 +1646,34 @@
 , data);
+%0A%0A    return true;
 %0A%7D%0A%0A/**%0A
@@ -2309,14 +2309,8 @@
 ort 
-async 
 func
@@ -2584,26 +2584,56 @@
 s;%0A%0A
-%0A      if(!(await 
+        setTimeout(function()%7B%0A%0A            if(!
 idx.
@@ -2717,17 +2717,16 @@
 ndex++))
-)
 %7B%0A%0A     
@@ -2724,24 +2724,32 @@
 )%7B%0A%0A        
+  
+      
 index_doc++;
@@ -2749,32 +2749,40 @@
 _doc++;%0A        
+      
+  
 index = 1;%0A%0A    
@@ -2785,21 +2785,23 @@
         
-await
+       
  self.ex
@@ -2857,28 +2857,26 @@
     
-%7D%0A%0A      return true
+      %7D%0A        %7D)
 ;%0A  
@@ -3343,21 +3343,16 @@
   return
- true
 ;%0A      
@@ -3368,31 +3368,13 @@
     
-return await lazyExport
+async
 (cal

revert changes made by Andrew Lee, fix issue #288