#pragma once

#include "la_5.h"
#include "la_tns.h"

/*                                | given to | given to    | array  |      */
/*                                |  user    | user  calls | setting|      */
/*                                | callback | and is used | needs  |      */
/*                                | callback | to recieve  | offset |      */
/*                                | callback | array config| hint   |      */
/*                                +----------+-------------+--------+      */
/*                                |   The    |             |        |      */
/*                                | DataBlock|    The      |  The   |      */
/* return value  |    Name        | Instance | Actual Data | Offset |      */
/*\             /                  \_        \             /      _/       */
/* \           /                     \_       \           /     _/         */
/*  \         /                        \_      \         /    _/           */
/*   \       /                           \_     \       /   _/             */
/*    \     /                              \     \     /  _/               */
typedef int (*laArrayGetLenF)(void *);
typedef int (*laIntGetF)(void *);
typedef void (*laIntSetF)(void *, int);
typedef void (*laIntReadF)(void *, int);
typedef void (*laIntArrayGetAllF)(void *, int *);
typedef void (*laIntArraySetF)(void *, int, int); //idx,n
typedef void (*laIntArraySetAllF)(void *, int);
typedef void (*laIntArraySetAllArrayF)(void *, int *);
typedef void (*laIntArrayReadAllF)(void *, int *);
typedef real (*laFloatGetF)(void *);
typedef void (*laFloatSetF)(void *, real);
typedef void (*laFloatReadF)(void *, real);
typedef void (*laFloatArrayGetAllF)(void *, real *);
typedef void (*laFloatArraySetF)(void *, int, real); //idx,n
typedef void (*laFloatArraySetAllF)(void *, real);
typedef void (*laFloatArraySetAllArrayF)(void *, real *);
typedef void (*laFloatArrayReadAllF)(void *, real *);
typedef int (*laEnumGetF)(void *);
typedef int (*laEnumGetLengthF)(void *);
typedef void (*laEnumSetF)(void *, int);
typedef void (*laEnumReadF)(void *, int);
typedef void (*laEnumArraySetF)(void *, int, int); //idx,n
typedef void (*laEnumArraySetAllF)(void *, int *);
typedef void (*laEnumArrayReadAllF)(void *, int *);
typedef void (*laEnumArrayGetAllF)(void *, int *);
typedef void (*laStringSetF)(void *, char *);
typedef void (*laStringGetF)(void *, char *copy_result, char** direct_result);
typedef void (*laStringReadF)(void *, char *);
typedef int (*laStringGetLenF)(void *);

typedef void (*laSubReadF)(void *, void *);         //from,set
typedef void *(*laSubGetInstanceF)(void *, void *); //from,iterator
typedef void (*laSubSetInstanceF)(void *, void *);
typedef void *(*laSubGetNextF)(void *, void *); //this,iterator
typedef int (*laSubGetAmountF)(void *);
typedef int (*laSubGetStateF)(void *);
typedef int (*laSubSetStateF)(void *, void *, int);
typedef void *(*laSubTypeDetachedGet)(void *, void *);
typedef void *(*laSubTypeDetachedGetNext)(void *, void *);
typedef void *(*laSubGetTypeF)(void *);// inst, returns type ref.
typedef int (*laSubUIFilterF)(void* parent, void* inst); // 1 show, 0 discard.
typedef void *(*laSubUIThemeF)(void* parent, void* inst); // return a theme, MAIN.CurrentTheme can always be referenced to produce invert.
typedef int (*laSubUIGapF)(void* parent, void* inst);
typedef void* (*laRawGetF)(void *, int* r_size, int* return_is_a_copy);
typedef int (*laRawGetSizeF)(void *);
typedef void (*laRawSetF)(void *, void* data, int copy_size);

typedef void (*laContainerPostReadFunc)(void *);
typedef laPropContainer* (*laGetNodeTypeFunc)(void *);
typedef void (*laContainerBeforeFreeF)(void *);
typedef void (*laContainerUndoTouchedF)(void *, u64bit hint);
typedef void (*laContainerpUDFPropagateF)(void *, void* udf, int Force);

#define LA_PROP_GENERAL_ROOT (1<<7)
#define LA_PROP_SUB (1<<8)
#define LA_PROP_INT (1<<9)
#define LA_PROP_FLOAT (1<<10)
#define LA_PROP_STRING (1<<11)
#define LA_PROP_ENUM (1<<12)
#define LA_PROP_STRING (1<<13)
#define LA_PROP_ARRAY (1<<14)
#define LA_PROP_PANEL (1<<15)
#define LA_PROP_UI (1<<16)
#define LA_PROP_OPERATOR (1<<17)
#define LA_PROP_MENU (1<<18)
#define LA_PROP_SELF_CONDITION (1<<19)
#define LA_PROP_BIN (1<<20)
#define LA_PROP_REF_LIST (1<<21)
#define LA_PROP_GENERIC_BITS (~LA_PROP_ARRAY)
#define LA_PROP_IS_FOLDER (1<<22)
#define LA_PROP_IS_FILE   (1<<23)
#define LA_PROP_RAW       (1<<24)

#define LA_PROP_OTHER_ALLOC (1<<3)
#define LA_PROP_HYPER_BITS (1|2)

#define LA_RAW_CSTR_MAX_LEN 4096

typedef void (*laUiDefineFunc)(void *uil, void *collection_inst, void *this_inst, void *extra_col, int temlpate_context);
typedef void (*laPanelDetachedPropFunc)(void *panel);

//typedef void(*laUnlinkFunc)(void*, void*);//this instance,target instance

NEED_STRUCTURE(laCanvasTemplate);
NEED_STRUCTURE(laKeyMapper);

STRUCTURE(laPropContainer){
    laListItem Item;

    const char *Identifier;
    const char *Name;
    const char *Description;

    uint32_t IconID;

    int NodeSize;

    laContainerBeforeFreeF BeforeFree;
    laContainerUndoTouchedF UndoTouched;
    laContainerpUDFPropagateF UDFPropagate;
    laContainerPostReadFunc PostRead;
    laContainerPostReadFunc PostReadIm;
    int Hyper;
    int OtherAlloc;

    laCanvasTemplate *Template2D;

    laListHandle Props;

    laUiDefineFunc UiDefine;

    laListHandle FailedNodes;
    laListHandle TrashBin;
    laListHandle LocalUsers;

    int validated;
};

NEED_STRUCTURE(laUiType);
NEED_STRUCTURE(laPanel);
NEED_STRUCTURE(laPropStep);

STRUCTURE(laPropPack){
    laPropStep *Go;
    void *EndInstance;
    laPropStep *LastPs;
    laPropPack *RawThis;
    char LastIndex;
    void *CopyRef;       //Also template creation
};

STRUCTURE(laProp){
    laListItem Item;
    laPropContainer *Container;

    int PropertyType;

    int ReadOnly;
    //laProp*      Detached;
    laPropPack DetachedPP;

    int Len;

    char ElementBytes;

    uint32_t IconID;

    const char *Identifier;
    const char *Name;
    const char *Description;
    const char *Prefix;
    const char *Unit;

    const char *ExtraInstructions;

    laArrayGetLenF GetLen;

    laPropContainer *SubExtra; //?
    laPropContainer *SubProp;

    laUiDefineFunc UiDefine;

    laUiType *DefaultUiType;
    int       DefaultFlags;

    int Offset;
    char OffsetIsPointer;
    char UDFIsRefer;
    char UDFNoCreate;
    char UDFIgnore;
    char UDFOnly;
    char UDFIsSingle;

    //int           SignalThrow;
    //int           SignalCatch;

    u64bit Tag;

    laListHandle UserPanels;
};

STRUCTURE(laPropUserPanel){
    laListItem Item;
    laPanel *Panel;
    laListHandle UserPacks;
};

STRUCTURE(laPropUser){
    laListItem Item;
    laPropStep *User;
    unsigned int FrameDistinguish;
};

STRUCTURE(laPropStep){
    laPropStep *pNext;
    laProp *p;
    char Type;
    void *UseInstance;
};

STRUCTURE(laPropLink){
    laListItem Item;
    laPropPack Recieve;
    laSafeString *Identifier;
    laProp *Prop;
    laPropStep FakePS;
    laPropPack PP;
    void *DataStowage;
};

STRUCTURE(laIntProp){
    laProp Base;
    laIntGetF Get;
    laIntSetF Set;
    laIntArraySetF SetArr;
    laIntArraySetAllF SetAll;
    laIntArraySetAllArrayF SetAllArr;
    laIntArrayGetAllF GetAll;

    laIntReadF Read;
    laIntArrayReadAllF ReadAll;

    int Step;
    int Min, Max;
    int DefVal;
    const int *DefArr;

    int *Detached;
};

STRUCTURE(laFloatProp){
    laProp Base;
    laFloatGetF Get;
    laFloatSetF Set;
    laFloatArraySetF SetArr;
    laFloatArraySetAllF SetAll;
    laFloatArraySetAllArrayF SetAllArr;
    laFloatArrayGetAllF GetAll;

    laFloatReadF Read;
    laFloatArrayReadAllF ReadAll;

    real Step;

    real Min, Max;
    real DefVal;
    const real *DefArr;

    real *Detached;
};

STRUCTURE(laEnumItem){
    laListItem Item;
    const char *Identifier;
    const char *Name;
    const char *Description;
    int Index;
    uint32_t IconID;
};

STRUCTURE(laEnumProp){
    laProp Base;
    laEnumGetF Get;
    laEnumGetLengthF GetLen;
    laEnumSetF Set;
    laEnumArraySetF SetArr;
    laEnumArraySetAllF SetAll;
    laEnumArrayGetAllF GetAll;

    laEnumReadF Read;
    laEnumArrayReadAllF ReadAll;

    laListHandle Items; //id start from 1.

    int DefVal;
    const int *DefArr;

    int *Detached;
};

STRUCTURE(laStringProp){
    laProp Base;
    laStringGetF Get;
    laStringSetF Set;
    laStringGetLenF Getstrlen;

    laStringReadF Read;

    char IsSafeString;

    const char *DefStr;

    char *Detached;
};

NEED_STRUCTURE(laOperatorType)

STRUCTURE(laOperatorProp){
    laProp Base;
    const char *OperatorID;
    laOperatorType *OperatorType;
};

STRUCTURE(laRawProp){
    laProp Base;
    laRawGetF RawGet;
    laRawSetF RawSet;
    laRawGetSizeF RawGetSize;
};

STRUCTURE(laSubProp){
    laProp Base;
    laSubGetInstanceF Get;
    laSubGetInstanceF GetActive;
    laSubSetInstanceF Set;
    laSubGetNextF GetNext;
    laSubGetStateF GetState;
    laSubSetStateF SetState;
    laSubGetAmountF GetAmount;
    laSubUIFilterF UiFilter;
    laSubUIThemeF GetTheme;
    laSubUIGapF GetGap;
    int ListHandleOffset;

    laSubTypeDetachedGet DetachedGet;
    laSubTypeDetachedGetNext DetachedGetNext;

    const char *TargetID;
    laGetNodeTypeFunc GetType;

    void *Detached;

    int IsRefList;
};

STRUCTURE(laPropIterator){
    laListItemPointer *Linker;
    void *Parent;
    void *Handle;
};

//STRUCTURE(laPropGroup) {
//	laListItem Item;
//	const char * Identifier;
//	const char * Name;
//	const char * Description;
//	//const char * Prefix;
//	//const char * Unit;
//
//	laListHandle Properties;
//};

STRUCTURE(laResourceFolder){
    laListItem Item;
    laSafeString* Path;
};

STRUCTURE(laRoot){
    laPropContainer *Root;
    void *RootInstance;
};
STRUCTURE(laUDFPostRead){
    laListItem Item;
    void *Instance;
    laContainerPostReadFunc Func;
};
//STRUCTURE(laUDFPointerSync) {
//	laListItem    Item;
//	void*        ReadPointer;
//	void*        ActualPointer;
//	char *        NUID;
//};
//STRUCTURE(laUDFPointerRecord) {
//	laListItem    Item;
//	void*        UseInstance;
//	laSubProp*    SubProp;
//	void**       PendingReference;
//	void*        ReadInstance;
//	char *        NUID;
//};


STRUCTURE(laPtrSync){
    laListItem Item; //hash
    void *RefDB;
    //void*     ReadRef;
    void *Parent; //key
    laSubProp *Prop;  //must be sub
};

STRUCTURE(laPtrSyncCommand){
    laListItem Item;
    laPtrSync *Target;
    void *ReadInstance;
    laUID ReadNUID;
};

STRUCTURE(laUDFPropSegment){
    laListItem Item;
    laPropPack *PPP;
    laPropPack PP;
    laSafeString *Path;
};
STRUCTURE(laUDFH2Instance){
    laListItem Item;
    laPropContainer* pc;
    void* Instance;
};
STRUCTURE(laUDF){
    int Opened;
    FILE *DiskFile;
    laSafeString *FileName;

    laListHandle     H2Instances;
    laUDFH2Instance* CurrentH2Instance;
    
    laListHandle PropsToOperate;
    //laListHandle  PointerSync;
    //laListHandle  PointerRecording;
    short NumSegmets;
    short Modified;
    short HasInstances;
    short Managed;

    u8bit *FileContent;
    u64bit Seek;

    long TotalRefs;

    laListHandle HyperRecords; //writing

    //laListHandle  LinkedFiles;    //writing and reading
    laListHandle OwnHyperItems; //reading
};
STRUCTURE(laUDFHyperRecordItem){
    laListItem Item;
    void* HyperUserMem;
    laPropContainer* pc;
    u64bit Seek;
};
STRUCTURE(laUDFRegistry){
    laListItem Item;
    laSafeString* Path;
};
STRUCTURE(laUDFOwnHyperItem){
    laListItem Item;
    laUID NUID;
    laUDFRegistry* Registry;
    u64bit Seek;
};
STRUCTURE(laTrashRestoreExtra){
    void *Instance;
    laListHandle Instances;
};
STRUCTURE(laManagedUDF){
    laListItem Item;
    laUDF* udf;
    laSafeString *BaseName; // update together
    laListHandle PropSegments;
};
STRUCTURE(laManagedSaveProp){
    laListItem Item;
    laSafeString* Path;
};
NEED_STRUCTURE(laUDFContentInstance);
STRUCTURE(laUDFContentNode){
    laListItem Item;
    laListHandle Instances;
    laSafeString *Identifier;
    laSafeString *FullPath;
    unsigned long FileSeek;
    laPropPack PP;
    laPropStep FakePS;
    laUDFContentInstance *Parent;
};
STRUCTURE(laUDFContentInstance){
    laListItem Item;
    laSafeString *Identifier;
    u64bit FileSeek;
    laUDFContentNode *Parent;
    laListHandle Children;
};

STRUCTURE(laDiff){
    laListItem Item;
    laListHandle Commands;
    laListHandle ExtraTouched;
    laSafeString* Description;
    u64bit Hint;
};
STRUCTURE(laDiffExtraTouched){
    laListItem Item;
    laDBInst* dbi;//ref, not owner
};
STRUCTURE(laDiffCommand){
    laListItem Item;
    laDBInst* Instance;
    laProp* p;
    void* Data; //for sub, this is dbinst.
};
STRUCTURE(laDiffCommandRaw){
    laListItem Item;
    laDBInst* Instance;
    laProp* p;
    void* Data; int DataSize;
};
STRUCTURE(laDiffCommandInst){
    laListItem Item;
    laDBInst* OriginalPrev;
    laDBInst* OriginalNext;
    laDBInst* BeforePrev;
    laDBInst* BeforeNext;
    laDBInst* DBInst;
};
STRUCTURE(laDiffCommandSub){
    laDiffCommand Base;
    laListHandle AddedInst;
    laListHandle RemovedInst;
    laListHandle MovedInst;
};
STRUCTURE(laDiffTemp){
    laListItem Item;
    void* p;
    void* tPrev;
    void* tNext;
    void* nPrev;
    void* nNext;
};

STRUCTURE(laDBRecordedProp){
    laListItem Item;
    laSafeString* OriginalPath;
};

STRUCTURE(laDBInstPendingRelink){
    laListItem Item;
    laDBInst* dbi; void* from; void* to;
};
STRUCTURE(laDBInst){
    laListItem Item;
    laListItem Item2;//DBInstLink
    void* OriginalInstance;
    laPropContainer* pc;
    laListHandle Props;
    laDiff* CreatedDiff;
    laDiff* DeletedDiff;
};
STRUCTURE(laDBProp){
    laListItem Item;
    laProp*    p;
    void*      Data;
    //---------------
};
;
STRUCTURE(laDBRawProp){
    laListItem Item;
    laProp*    p;
    void*      Data;
    //---------------
    int        DataSize;
};
STRUCTURE(laDBSubProp){
    laListItem Item;
    laProp*    p;
    void*      Data;
    //---------------
    laListHandle Instances;
};

STRUCTURE(laDiffPtrSync){
    laListItem Item;
    void* instance;
    laDBProp* dbp;
    laDiffCommand* dc;
};

STRUCTURE(laDiffPost){
    laListItem Item;
    void* instance;
    laContainerUndoTouchedF Touched;
};


    //STRUCTURE(laUDFFailNode) {
    //	laListItemPointer Item;
    //	laPropContainer*  pc;
    //};

/* Only little endian are supported right now */
#define LA_UDF_IDENTIFIER "UDF_LE"

#define LA_UDF_MARK_TIMESTAMP 3

#define LA_UDF_MODE_APPEND 0
#define LA_UDF_MODE_OVERWRITE 1

#define LA_UDF_SINGLE       (1<<0)
#define LA_UDF_COLLECTION   (1<<1)
#define LA_UDF_REFER        (1<<2)
#define LA_UDF_ITEM         (1<<3) //ItemType
#define LA_UDF_ACTIVE (1<<4)
#define LA_UDF_STATE (1<<5)
#define LA_UDF_REGULAR_MARK_64 (1<<6)
#define LA_UDF_ARRAY_MARK_64 (1<<7)
#define LA_UDF_HYPER_ITEM (1<<8)  //ItemType
#define LA_UDF_SHARE_RESOURCE (1<<9)
#define LA_UDF_USE_VERSION (1<<10) //Use History
#define LA_UDF_REGULAR_MARK_32 (1<<10)
#define LA_UDF_ARRAY_MARK_32 (1<<11)
#define LA_UDF_STRING_MARK (1<<12)
#define LA_UDF_HYPER_MARK (1<<13)
#define LA_UDF_ONLY (1<<14)
#define LA_UDF_RAW_MARK (1<<14)
//#define LA_UDF_LINKED_ITEM (1<<15) //ItemType
#define LA_UDF_IGNORE (1<<16)
#define LA_DETACHABLE (1<<17)
#define LA_UDF_VARIABLE_NODE_SIZE (1<<18)
#define LA_UDF_FIXED_NODE_SIZE (1<<19)
#define LA_UDF_LOCAL (1<<20)
#define LA_UDF_IS_RAD (1<<21)
#define LA_UDF_PRINT_STATICS (1<<22)
#define LA_UDF_NUID_SEEK (1<<23)
#define LA_UDF_NUID_LINK_FILES (1<<24)
#define LA_AS_IDENTIFIER (1<<25)
#define LA_UDF_USE_LINK_NODE (1<<26)
#define LA_READ_ONLY (1<<27)

STRUCTURE(laThreadNotifier){
    laListItem Item;
    char Path[256];
};

laPropContainer *laDefineRoot();

NEED_STRUCTURE(laOperatorType)
NEED_STRUCTURE(laOperator)
NEED_STRUCTURE(laEvent)

void *laget_ListNext(laListItem *Item, void *UNUSED);
void *laget_ListPrev(laListItem *Item, void *UNUSED);
void *laget_List2Next(laListItem2 *Item, void *UNUSED);
void *laget_List2Prev(laListItem2 *Item, void *UNUSED);

void la_DEBUG_VerifyThisContainer(laPanel *pa, laPropContainer *pc);
void la_DEBUG_VerifyPanelPropsDestroyed(laPanel *p);

void la_CopyPropPack(laPropPack *From, laPropPack *To);
void laPropPackToLocal(laPropPack* ToPP, laPropPack* pp);

laPropContainer* la_EnsureSubTarget(laSubProp* sp, void* optional_instance);

laPropContainer *la_ContainerLookup(char *ID);
laProp *la_PropLookup(laListHandle *lst, char *ID);

void la_UsePropPack(laPropPack *pp, int ForceRecalc);
void la_StopUsingPropPack(laPropPack *pp);
void la_SetPropMathcerContext(laPanel *p);
void laNotifyUsersPP(laPropPack *pp);
void laNotifyUsersPPPath(laPropPack *pp, char *path);
void laNotifySubPropUsers(laProp *p, void *Instance);
void laNotifyUsers(char *Path);
void laNotifyInstanceUsers(void *Instance);
void laThreadNotifyUsers(char *Path);

int laIsPropertyReadOnly(laPropPack *pp);

int laGetPrefixP(laPropPack *p, char buf[8][64]);
int laGetPrefix(laProp *p, char buf[8][64]);

laPropContainer* laGetInstanceType(laPropPack* pp, void* instance);
laUiDefineFunc* laGetPropertyUiDefine(laPropPack* pp, void* instance);

int laSetInt(laPropPack *pp, int n);
int laGetInt(laPropPack *pp);
int laSetFloat(laPropPack *pp, real n);
real laGetFloat(laPropPack *pp);
int laGetArrayLength(laPropPack *pp);
int laSetIntArraySingle(laPropPack *pp, int index, int n);
int laSetIntArrayAll(laPropPack *pp, int n);
int laSetIntArrayAllArray(laPropPack *pp, int *arr);
int laGetIntArray(laPropPack *pp, int *result);
int laSetFloatArraySingle(laPropPack *pp, int index, real n);
int laSetFloatArrayAll(laPropPack *pp, real n);
int laSetFloatArrayAllArray(laPropPack *pp, real *arr);
int laGetFloatArray(laPropPack *pp, real *result);
laEnumItem *laGetEnum(laPropPack *pp);
laEnumItem *laGetEnumEntryLen(laPropPack *pp);
laEnumItem *laGetEnumArrayIndexed(laPropPack *pp, int index);
int laGetEnumArray(laPropPack *pp, laEnumItem **result);
laEnumItem *laGetEnumFromIdentifier(laEnumProp *p, char *Identifier);
int laEnumHasIcon(laPropPack *pp);
int laSetEnumExternal(laPropPack *pp, int n);
int laSetEnum(laPropPack *pp, int n);
int laSetEnumArrayIndexedExternal(laPropPack *pp, int index, int n);
int laSetEnumArrayIndexed(laPropPack *pp, int index, int n);
int laSetEnumArrayAllArray(laPropPack* pp, laEnumItem** ei);
int laSetEnumArrayAll(laPropPack* pp, int EnumN);
int laSetString(laPropPack *pp, char *str);
int laGetString(laPropPack *pp, char *result, char** direct_result);
int laActuateProp(laPropPack *This, laPropPack *RunPP, laOperator *OptionalFrom, laEvent *e);
int laGetIntRange(laPropPack *pp, int *min, int *max);
int laGetFloatRange(laPropPack *pp, real *min, real *max);
void* laGetRaw(laPropPack *pp, int* r_size, int* return_is_a_copy);
int laSetRaw(laPropPack *pp, void* data, int _size);

void laMarkPropChanged(laPropPack* pp);

void *la_FindMatchingInstance(void *From, laProp *Sub, laProp *p, laPropStep *Value);

void la_FreePropStepCache(laPropStep *GoTarget);
void la_StepPropPack(laPropPack *pp);

void la_GetPropPackFullPath(laPropPack *pp, char *result);
void la_GetPropPackPath(laPropPack *pp, char *result);

laItemUserLinker *laUseDataBlock(void* HyperUserMem, laProp *Which, unsigned int FrameDistinguish, void *User, laUserRemoveFunc Remover, int ForceRecalc);
void laStopUsingDataBlock(void* HyperUserMem, laProp *prop, laPanel *p);
void laDataBlockNoLongerExists(void *HyperUserMem, laListHandle* UserList);

void laThrowToTrashBin(void* Data, char *ContainerString);


void la_FreeProperty(laProp* p);
void la_FreePropertyContainer(laPropContainer* pc);

laPropContainer *laAddPropertyContainer(const char *Identifier, const char *Name, const char *Description, uint32_t IconID, laUiDefineFunc DefaultUiDefine,
                                        int NodeSize, laContainerPostReadFunc PostRead, laContainerPostReadFunc PostReadIm, int IsHyper);
void laPropContainerExtraFunctions(laPropContainer* pc, laContainerBeforeFreeF BeforeFree, laContainerUndoTouchedF UndoTouched, laContainerpUDFPropagateF UDFPropagate);
const char *la_GetPropertyTypeString(int Type);

NEED_STRUCTURE(laWidget);

laProp *la_CreateProperty(laPropContainer *Container, int Type, const char *Identifier, const char *Name, const char *Description,
                          const char *Prefix, const char *Unit, laWidget* DefaultWidget, u64bit Tag);
laProp *la_MakeDetachedProp(laPanel* p, const char *From, const char *Rename);
laProp *laAddIntProperty(laPropContainer *Container, const char *Identifier, const char *Name, const char *Description, laWidget* DefaultWidget,
                         const char *Prefix, const char *Unit, int Max, int Min, int Step, int DefVal, const int *DefArr,
                         int OffsetSize, laIntGetF Get, laIntSetF Set, int ArrayLength, laArrayGetLenF GetLen,
                         laIntArraySetF SetArr, laIntArrayGetAllF GetAll, laIntArraySetAllF SetAll, laIntArraySetAllArrayF SetAllArr,
                         laIntReadF Read, laIntArrayReadAllF ReadAll,
                         u64bit Tag);

laProp *laAddFloatProperty(laPropContainer *Container, const char *Identifier, const char *Name, const char *Description, laWidget* DefaultWidget,
                           const char *Prefix, const char *Unit, real Max, real Min, real Step, real DefVal, const real *DefArr,
                           int OffsetSize, laFloatGetF Get, laFloatSetF Set, int ArrayLength, laArrayGetLenF GetLen,
                           laFloatArraySetF SetArr, laFloatArrayGetAllF GetAll, laFloatArraySetAllF SetAll, laFloatArraySetAllArrayF SetAllArr,
                           laFloatReadF Read, laFloatArrayReadAllF ReadAll,
                           u64bit Tag);

laProp *laAddEnumProperty(laPropContainer *Container, const char *Identifier, const char *Name, const char *Description, laWidget* DefaultWidget,
                          const char *Prefix, const char *Unit, int DefVal, const int *DefArr,
                          int OffsetSize, laEnumGetF Get, laEnumSetF Set, int ArrayLength, laArrayGetLenF GetLen,
                          laEnumArraySetF SetArr, laEnumArrayGetAllF GetAll, laEnumArraySetAllF SetAll,
                          laEnumReadF Read, laEnumArrayReadAllF ReadAll,
                          u64bit Tag);

int laAddEnumItem(laProp *p, const char *Identifier, const char *Name, const char *Description, uint32_t IconID);
int laAddEnumItemAs(laProp *p, const char *Identifier, const char *Name, const char *Description, int Index, uint32_t IconID);

laProp *laAddStringProperty(laPropContainer *Container, const char *Identifier, const char *Name, const char *Description, laWidget* DefaultWidget,
                            const char *Prefix, const char *Unit, const char *DefStr,
                            int IsSafeString, int OffsetSize, laStringGetLenF GetLen, laStringGetF Get, laStringSetF Set,
                            laStringReadF Read,
                            u64bit Tag);

laProp *laAddSubGroup(laPropContainer *Container, const char *Identifier, const char *Name, const char *Description,
                      const char *TargetId, laGetNodeTypeFunc GetType, laWidget* DefaultWidget, laUiDefineFunc DefaultUiDef,
                      int OffsetSize, laSubGetInstanceF Get, laSubGetInstanceF GetActive, laSubGetNextF GetNext, laSubSetInstanceF Set,
                      laSubGetStateF GetState, laSubSetStateF SetState, int ListHandleOffset, u64bit Tag);
void laSubGroupExtraFunctions(laProp* p, laSubUIFilterF* UiFilter, laSubUIThemeF* GetTheme, laSubUIGapF GetGap);
void laSubGroupDetachable(laProp *SubProp, laSubTypeDetachedGet DetachedGet, laSubTypeDetachedGetNext DetachedGetNext);

laProp *laAddOperatorProperty(laPropContainer *Container, const char *Identifier, const char *Name, const char *Description,
                              const char *OperatorID, uint32_t IconID, laWidget* DefaultWidget);

laProp *laAddRawProperty(laPropContainer *Container, const char *Identifier, const char *Name, const char *Description, int OffsetSize, laRawGetSizeF GetSize, laRawGetF RawGet, laRawSetF RawSet, u64bit Tag);

//void laPropertySignal(laProp* p, int Throw, int Catch);

NEED_STRUCTURE(laBoxedTheme);

void *laGetInstance(laProp *sub, void *ThisInstance, laPropIterator *pi);
void *laGetNextInstance(laProp *sub, void *FromInstance, laPropIterator *pi);
void *laGetActiveInstanceStrict(laProp *sub, void *FromInstance);
void *laGetActiveInstance(laProp *sub, void *FromInstance, laPropIterator *pi);
void laSetActiveInstance(laProp *sub, void *FromInstance, void *Instance);
void laAppendInstance(laSubProp *sub, void *FromInstance, void *Instance);
int laGetUiState(laProp *sub, void *Instance);
laBoxedTheme* laGetUiTheme(laProp *sub, void* parent, void *Instance);
int laGetUiGap(laProp *sub, void* parent, void *Instance);
int laCanGetState(laProp *sub);
int laCanGetTheme(laProp *sub);
int laCanGetGap(laProp *sub);
int laSetState(laProp *sub, void *FromInstance, void *Instance, int State);

laPropContainer *la_SetGeneralRoot(laPropContainer **GeneralRoot, const char *Identifier, const char *Name, const char *Description);

int la_GetPropFromPath(laPropPack *Self, laPropPack *Base, const char *Path, void **SpecifiedInstance);
laProp *la_GetGeneralPropFromPath(laProp *General, const char *Path);

int laValidateProperties();

void laSetRootInstance(void *root);

void la_RegisterMainUiTypes();
void la_RegisterMainThemes();
void la_RegisterInternalTemplates();
void la_RegisterInternalProps();

void la_PrintPropStructure();

laProp *la_GetGeneralProp(laProp *p);

void* laget_InstanceActiveUDF(void* instance);
void laset_InstanceUDF(void* instance, void* set);

void la_UDFAppendSharedTypePointer(char *ID, void *Pointer);

void la_AppendLinkedFile(laUDF *File);

void la_GetWorkingDirectoryInternal();
int laGetRelativeDirectory(char *FullFrom, char *FullTo, char *Result);
void laGetUDFRelativeDirectory(laUDF *From, laUDF *To, char *Result);
void laGetFullPath(char *FullFrom, char *Relative, char *Result);

laUDF *laPrepareUDF(char *FileName);
int laWriteProp(laUDF *udf, char *Path);
int laWritePropP(laUDF *udf, laPropPack *pp);
int laPackUDF(laUDF *udf, int UseInstanceList);

void laSaveProp(char* path);
void laClearSaveProp();

int laRegisterModifications(int ReturnIfAnyMod, int ReturnIfAnyEmpty, int* rempty, int RegisterToUDF);

laUDF *laOpenUDF(char *FileName, int ReadToMemory, laUDFRegistry* ReadRegistryRef, laManagedUDF** UseManaged);
void laCloseUDF(laUDF *udf);
int laExtractUDF(laUDF *udf, laManagedUDF* mUDF, int Mode, laListHandle *Parent);

laUDFOwnHyperItem* laFindHyperItem(laPropContainer* pc, char* uid);
laUDFRegistry* laFindUDFRegistry(char* Path);
laUDFRegistry* laCreateUDFRegistry(char* Path);
void laClearUDFRegistries();
void laRefreshUDFRegistries();

laManagedUDF* la_FindManagedUDF(char* FileName);
laManagedUDF* la_EnsureManagedUDF(char* FileName, int PutAtTop);
void la_MakeDummyManagedUDF();
void laStopManageUDF(laManagedUDF* m);
void laClearManagedUDF();

void laSaveManagedUDF();

void laPropagateUDF(laPropContainer* pc, void* inst, int force);

//================== manifest

void laAddResourceFolder(char* Path);
void laRemoveResourceFolder(laResourceFolder* rf);
void la_ClearUDFRegistryAndFolders();

//================== undo


void laPrintDBInstInfo();
void la_NoLongerRecordUndo();

void laAddRootDBInst(char* path);
void laPushDifferences(char* Description, u64bit hint);
int laRecordDifferences(laPropPack* base, char* path);
int laRecordInstanceDifferences(void* instance, const char* container);
void laRecordAndPush(laPropPack* base, char* path, char* description, uint64_t hint);
void laRecordAndPushProp(laPropPack* base, char* path);
void laRecordEverythingAndPush();

void laUndo();
void laRedo();