const SmartDict = require("./SmartDict");
const StructuredBlock = require("./StructuredBlock");
const MutableBlock = require("./MutableBlock");
const KeyChain = require("./KeyChain");
const KeyPair = require("./KeyPair");
const AccessControlList = require("./AccessControlList");
const Dweb = require("./Dweb");

//TODO-SEPERATE - move these to Dweb
const LetterToClass = { // Each of these needs a constructor that takes hash, data and is ok with no other parameters, (otherwise define a set of these methods as factories)
    "sb": StructuredBlock,
    "kc": KeyChain,
    "kp": KeyPair,
    "mb": MutableBlock,
    "acl": AccessControlList,
    //"accesscontrollistentry", AccessControlListEntry - not listed as AccessControlListEntry is not exposed
};

class UnknownBlock extends SmartDict {
    /*
     A class for when we don't know if its a StructuredBlock, or MutableBlock or something else

     You could use this by: (OBSOLETED) foo = new UnknownBlock(hash, verbose); foo.p_load(verbose, ["addtoparent",parent])
     */

    constructor(hash, verbose) {
        // Note Python has options field that overrides data but triggers error as unimplemented as of 2017-05-27
        super(hash, null, verbose, null);
    }
    p_fetch(verbose, successmethod) {
        /*
            Fetch a block which initially we don't know which type
            :return: New object - e.g. StructuredBlock or MutableBlock
         */
        if (verbose) console.log("Unknownblock loading", this._hash);
        let self = this;
        let cls;
        return Dweb.transport.p_rawfetch(this._hash, verbose)
            .then((data) => {
                data = Dweb.transport.loads(data);    // Parse JSON
                let table = data["table"];
                cls = LetterToClass[table];
                console.assert(cls, "UnknownBlock.p_fetch:",table,"isnt implemented in LetterToClass");
                return data;
            })
            .then((data) => Dweb.CryptoLib.p_decryptdata(data, verbose))    // decrypt - may return string or obj
            .then((data) => {
                let newobj = new cls(self._hash, data);
                if (successmethod) {
                    let methodname = successmethod.shift();
                    //if (verbose) console.log("p_elem",methodname, successmethod);
                    newobj[methodname](...successmethod); // Spreads successmethod into args, like *args in python
                }
                return newobj;    // For chaining
            })
            .catch((err) => {console.log("cant fetch and decrypt",this); throw(err)});
    }
}


exports = module.exports = UnknownBlock;

@@ -39,246 +39,8 @@
 %22);%0A
-const StructuredBlock = require(%22./StructuredBlock%22);%0Aconst MutableBlock = require(%22./MutableBlock%22);%0Aconst KeyChain = require(%22./KeyChain%22);%0Aconst KeyPair = require(%22./KeyPair%22);%0Aconst AccessControlList = require(%22./AccessControlList%22);%0A
 cons
@@ -111,25 +111,23 @@
 b%0Aconst 
-LetterToC
+table2c
 lass = %7B
@@ -287,16 +287,17 @@
   %22sb%22: 
+%22
 Structur
@@ -299,24 +299,25 @@
 ucturedBlock
+%22
 ,%0A    %22kc%22: 
@@ -320,16 +320,17 @@
 c%22: 
+%22
 KeyChain
 ,%0A  
@@ -325,16 +325,17 @@
 KeyChain
+%22
 ,%0A    %22k
@@ -342,15 +342,17 @@
 p%22: 
+%22
 KeyPair
+%22
 ,%0A  
@@ -359,16 +359,17 @@
   %22mb%22: 
+%22
 MutableB
@@ -372,16 +372,17 @@
 bleBlock
+%22
 ,%0A    %22a
@@ -386,16 +386,17 @@
  %22acl%22: 
+%22
 AccessCo
@@ -404,16 +404,17 @@
 trolList
+%22
 ,%0A    //
@@ -1530,29 +1530,266 @@
 s = 
-LetterToClass%5Btable%5D;
+Dweb%5Btable2class%5Btable%5D%5D; // Gets class name, then looks up in Dweb - avoids dependency%0A                //console.log(%22XXX@UB.p_fetch.38 cls=%22,cls)%0A                console.assert(cls.prototype instanceof SmartDict, %22Avoid data driven hacks to other classes%22)
 %0A   
@@ -1876,17 +1876,15 @@
  in 
-LetterToC
+table2c
 lass

Remove dependencies in UnknownBlock - on other classes.