MiteTricks
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// ©kaigouthro
// @version=5

// please let e know abot any bugs,
// if you can fix them, please pass them back to me.

// @description Matrix Global Registry. 
// Get, Set, automatic growing, universal get/set, 
// multimatrix dictionaries, multidicitionary matrixes..
// add slice matrixes of any type, sare one commoon global key registry
// pull up an item from a category, and item name ie a table of info. 
// same cell needs a color, a size, a string, a value, etc..
// all of which can be pulled up with trhe same group id, and key id.
// just swap which matrix you pull the value from.
// this has a side benefit of notrepainting and recalculating
// when pulling values, changing inputs..
// makes for very fast/clean usage..
library("MiteTricks",  true)

var int _REG_SIZE = input.int(3, 'Registry Size', step=1, minval=2, maxval=100)

// @function Registry inititalizer
// @returns registry of string mttrix type
export initRegistry   () =>
    varip matrix<string> _REGISTRY = matrix.new<string> (4, 4, string(na)), matrix.set(_REGISTRY,0,0,' '), _REGISTRY

// @function    create bool      type  new matrix presized 2x2 for reg
// @param       optional row size
// @param       optional column size
// @param       optional fill value(default is bool    (na)
// @returns     bool matrix of specified size and fill, or blank 2x2 for registry use
export newbool      ( int _r = 2, int _c = 2, bool         fill = na ) => var matrix<bool>     _ValReg = matrix.new<bool>      (_r , _c, bool      ( fill ) ),  _ValReg

// @function    create box       type  new matrix presized 2x2 for reg
// @param       optional row size
// @param       optional column size
// @param       optional fill value(default is box     (na)
// @returns     box matrix of specified size and fill, or blank 2x2 for registry use
export newbox       ( int _r = 2, int _c = 2, box          fill = na ) => var matrix<box>      _ValReg = matrix.new<box>       (_r , _c, box       ( fill ) ),  _ValReg

// @function    create color     type  new matrix presized 2x2 for reg
// @param       optional row size
// @param       optional column size
// @param       optional fill value(default is color   (na)
// @returns     color matrix of specified size and fill, or blank 2x2 for registry use
export newcolor     ( int _r = 2, int _c = 2, color        fill = na ) => var matrix<color>    _ValReg = matrix.new<color>     (_r , _c, color     ( fill ) ),  _ValReg

// @function    create float     type  new matrix presized 2x2 for reg
// @param       optional row size
// @param       optional column size
// @param       optional fill value(default is float   (na)
// @returns     float matrix of specified size and fill, or blank 2x2 for registry use
export newfloat     ( int _r = 2, int _c = 2, float        fill = na ) => var matrix<float>    _ValReg = matrix.new<float>     (_r , _c, float     ( fill ) ),  _ValReg

// @function    create int       type  new matrix presized 2x2 for reg
// @param       optional row size
// @param       optional column size
// @param       optional fill value(default is int     (na)
// @returns     int matrix of specified size and fill, or blank 2x2 for registry use
export newint       ( int _r = 2, int _c = 2, int          fill = na ) => var matrix<int>      _ValReg = matrix.new<int>       (_r , _c, int       ( fill ) ),  _ValReg

// @function    create label     type  new matrix presized 2x2 for reg
// @param       optional row size
// @param       optional column size
// @param       optional fill value(default is label   (na)
// @returns     label matrix of specified size and fill, or blank 2x2 for registry use
export newlabel     ( int _r = 2, int _c = 2, label        fill = na ) => var matrix<label>    _ValReg = matrix.new<label>     (_r , _c, label     ( fill ) ),  _ValReg

// @function    create line      type  new matrix presized 2x2 for reg
// @param       optional row size
// @param       optional column size
// @param       optional fill value(default is line    (na)
// @returns     line matrix of specified size and fill, or blank 2x2 for registry use
export newline      ( int _r = 2, int _c = 2, line         fill = na ) => var matrix<line>     _ValReg = matrix.new<line>      (_r , _c, line      ( fill ) ),  _ValReg

// @function    create linefill  type  new matrix presized 2x2 for reg
// @param       optional row size
// @param       optional column size
// @param       optional fill value(default is linefill(na)
// @returns     linefill matrix of specified size and fill, or blank 2x2 for registry use
export newlinefill  (int _r = 2, int _c = 2,  linefill     fill = na ) => var matrix<linefill> _ValReg = matrix.new<linefill>  (_r , _c, linefill  ( fill ) ),  _ValReg

// @function    create string    type  new matrix presized 2x2 for reg
// @param       optional row size
// @param       optional column size
// @param       optional fill value(default is string  (na)
// @returns     string matrix of specified size and fill, or blank 2x2 for registry use
export newstring    ( int _r = 2, int _c = 2, string       fill = na ) => var matrix<string>   _ValReg = matrix.new<string>    (_r , _c, string    ( fill ) ),  _ValReg

// @function    create table     type  new matrix presized 2x2 for reg
// @param       optional row size
// @param       optional column size
// @param       optional fill value(default is table   (na)
// @returns     table matrix of specified size and fill, or blank 2x2 for registry use
export newtable     ( int _r = 2, int _c = 2, table        fill = na ) => var matrix<table>    _ValReg = matrix.new<table>     (_r , _c, table     ( fill ) ),  _ValReg

// @function newfrom Matrix full of item input
// @param INIT_FILL item to fill (2x2) the matri and set type. a type(na) works
export newfrom      ( bool             INIT_FILL                     ) => var matrix<bool>     _ValReg = matrix.new<bool>      (2, 2, INIT_FILL),  _ValReg
export newfrom      ( box              INIT_FILL                     ) => var matrix<box>      _ValReg = matrix.new<box>       (2, 2, INIT_FILL),  _ValReg
export newfrom      ( color            INIT_FILL                     ) => var matrix<color>    _ValReg = matrix.new<color>     (2, 2, INIT_FILL),  _ValReg
export newfrom      ( float            INIT_FILL                     ) => var matrix<float>    _ValReg = matrix.new<float>     (2, 2, INIT_FILL),  _ValReg
export newfrom      ( int              INIT_FILL                     ) => var matrix<int>      _ValReg = matrix.new<int>       (2, 2, INIT_FILL),  _ValReg
export newfrom      ( label            INIT_FILL                     ) => var matrix<label>    _ValReg = matrix.new<label>     (2, 2, INIT_FILL),  _ValReg
export newfrom      ( line             INIT_FILL                     ) => var matrix<line>     _ValReg = matrix.new<line>      (2, 2, INIT_FILL),  _ValReg
export newfrom      ( linefill         INIT_FILL                     ) => var matrix<linefill> _ValReg = matrix.new<linefill>  (2, 2, INIT_FILL),  _ValReg
export newfrom      ( string           INIT_FILL                     ) => var matrix<string>   _ValReg = matrix.new<string>    (2, 2, INIT_FILL),  _ValReg
export newfrom      ( table            INIT_FILL                     ) => var matrix<table>    _ValReg = matrix.new<table>     (2, 2, INIT_FILL),  _ValReg

// Helpers for NA vals (prevents errors on reads later on)
_n(bool     i)=> a = array.new<bool>     (1000,i), array.fill(a,bool     (na)), a
_n(box      i)=> a = array.new<box>      (1000,i), array.fill(a,box      (na)), a
_n(color    i)=> a = array.new<color>    (1000,i), array.fill(a,color    (na)), a
_n(float    i)=> a = array.new<float>    (1000,i), array.fill(a,float    (na)), a
_n(int      i)=> a = array.new<int>      (1000,i), array.fill(a,int      (na)), a
_n(label    i)=> a = array.new<label>    (1000,i), array.fill(a,label    (na)), a
_n(line     i)=> a = array.new<line>     (1000,i), array.fill(a,line     (na)), a
_n(linefill i)=> a = array.new<linefill> (1000,i), array.fill(a,linefill (na)), a
_n(string   i)=> a = array.new<string>   (1000,i), array.fill(a,string   (na)), a
_n(table    i)=> a = array.new<table>    (1000,i), array.fill(a,table    (na)), a

import kaigouthro/columns/1
import kaigouthro/rows/1

// ========== core functions > autosizer/setter
getidx( _array ,  _KEY  )   => _idx = array.indexof ( _array , _KEY ) , _idx :=_idx >= 0 ? _idx : na

_checkrow(a,b,r) =>
    aa  = _n(matrix.get(a,0,0))
    ab  = _n(matrix.get(b,0,0))
    id  =  array.indexof (r,array.get(aa,0)), size = array.size(r) -2
    _rws = matrix.rows(a)
    if id  >= size
        columns.push(a,array.slice(aa,0,_rws))
    while matrix.columns(a) > matrix.columns (b)
        columns.push(b,array.slice(ab,0,_rws))

_checkcol(a,b,c) =>
    aa  = _n(matrix.get(a,0,0))
    ab  = _n(matrix.get(b,0,0))
    id  =  array.indexof (c,array.get(aa,0)), size = array.size(c) -2
    _cols = matrix.columns(a)
    if id  >= size
        rows.push(a,array.slice(aa,0,_cols))
    while matrix.rows(a) > matrix.rows (b)
        rows.push(b,array.slice(ab,0,_cols))


getcoords(_KEYREG, _GROUP, _KEY)  =>
    _G = getidx (matrix.row (_KEYREG , 0 ) ,    _GROUP )        
    _K = getidx (matrix.col (_KEYREG , na(_G) ? 0 : _G ), _KEY )
    [_K,_G]

// get function :
//
//  value matrix of current value slice
//  key registry (master reg, or different registries for different sub-scripts
//  group - can be the idnumber of the group, or the string name..
//  key   - can be the idnumber of the key, or the string name..
//  doesn't discriminate..  
//
//  one 'get' to rule hem all!

// get from any matrix by group name and item name or index nums.. 
// (same group and item name map to whichever key registry and they can OVERLAP!!!)\
// @function get Grabs value and returns single item                                                                                                                                                                                                                                                    
// @param _VALS    Matrix Values slice
// @param _KEYREG  Registry values matrix (strings)
// @param _GROUP   name of group/category or int group key
// @param _KEY     name of item to fetch from value rregistry or int key id
// @returns item from vals re
export get (  matrix<bool>     _VALS, matrix<string>  _KEYREG,   string _GROUP , string _KEY    ) => [_K, _G] = getcoords(  _KEYREG   , _GROUP ,  _KEY   ) , out  =   matrix.get ( _VALS ,  _K   ,  _G     )
export get (  matrix<box>      _VALS, matrix<string>  _KEYREG,   string _GROUP , string _KEY    ) => [_K, _G] = getcoords(  _KEYREG   , _GROUP ,  _KEY   ) , out  =   matrix.get ( _VALS ,  _K   ,  _G     )
export get (  matrix<color>    _VALS, matrix<string>  _KEYREG,   string _GROUP , string _KEY    ) => [_K, _G] = getcoords(  _KEYREG   , _GROUP ,  _KEY   ) , out  =   matrix.get ( _VALS ,  _K   ,  _G     )
export get (  matrix<float>    _VALS, matrix<string>  _KEYREG,   string _GROUP , string _KEY    ) => [_K, _G] = getcoords(  _KEYREG   , _GROUP ,  _KEY   ) , out  =   matrix.get ( _VALS ,  _K   ,  _G     )
export get (  matrix<int>      _VALS, matrix<string>  _KEYREG,   string _GROUP , string _KEY    ) => [_K, _G] = getcoords(  _KEYREG   , _GROUP ,  _KEY   ) , out  =   matrix.get ( _VALS ,  _K   ,  _G     )
export get (  matrix<label>    _VALS, matrix<string>  _KEYREG,   string _GROUP , string _KEY    ) => [_K, _G] = getcoords(  _KEYREG   , _GROUP ,  _KEY   ) , out  =   matrix.get ( _VALS ,  _K   ,  _G     )
export get (  matrix<line>     _VALS, matrix<string>  _KEYREG,   string _GROUP , string _KEY    ) => [_K, _G] = getcoords(  _KEYREG   , _GROUP ,  _KEY   ) , out  =   matrix.get ( _VALS ,  _K   ,  _G     )
export get (  matrix<string>   _VALS, matrix<string>  _KEYREG,   string _GROUP , string _KEY    ) => [_K, _G] = getcoords(  _KEYREG   , _GROUP ,  _KEY   ) , out  =   matrix.get ( _VALS ,  _K   ,  _G     )
export get (  matrix<linefill> _VALS, matrix<string>  _KEYREG,   string _GROUP , string _KEY    ) => [_K, _G] = getcoords(  _KEYREG   , _GROUP ,  _KEY   ) , out  =   matrix.get ( _VALS ,  _K   ,  _G     )
export get (  matrix<table>    _VALS, matrix<string>  _KEYREG,   string _GROUP , string _KEY    ) => [_K, _G] = getcoords(  _KEYREG   , _GROUP ,  _KEY   ) , out  =   matrix.get ( _VALS ,  _K   ,  _G     )
export get (  matrix<bool>     _VALS, matrix<string>  _KEYREG,   string _GROUP , int    _KEY    ) => [_K, _G] = getcoords(  _KEYREG   , _GROUP ,  _GROUP ) , out  =   matrix.get ( _VALS ,  _KEY ,  _G     )
export get (  matrix<box>      _VALS, matrix<string>  _KEYREG,   string _GROUP , int    _KEY    ) => [_K, _G] = getcoords(  _KEYREG   , _GROUP ,  _GROUP ) , out  =   matrix.get ( _VALS ,  _KEY ,  _G     )
export get (  matrix<color>    _VALS, matrix<string>  _KEYREG,   string _GROUP , int    _KEY    ) => [_K, _G] = getcoords(  _KEYREG   , _GROUP ,  _GROUP ) , out  =   matrix.get ( _VALS ,  _KEY ,  _G     )
export get (  matrix<float>    _VALS, matrix<string>  _KEYREG,   string _GROUP , int    _KEY    ) => [_K, _G] = getcoords(  _KEYREG   , _GROUP ,  _GROUP ) , out  =   matrix.get ( _VALS ,  _KEY ,  _G     )
export get (  matrix<int>      _VALS, matrix<string>  _KEYREG,   string _GROUP , int    _KEY    ) => [_K, _G] = getcoords(  _KEYREG   , _GROUP ,  _GROUP ) , out  =   matrix.get ( _VALS ,  _KEY ,  _G     )
export get (  matrix<label>    _VALS, matrix<string>  _KEYREG,   string _GROUP , int    _KEY    ) => [_K, _G] = getcoords(  _KEYREG   , _GROUP ,  _GROUP ) , out  =   matrix.get ( _VALS ,  _KEY ,  _G     )
export get (  matrix<line>     _VALS, matrix<string>  _KEYREG,   string _GROUP , int    _KEY    ) => [_K, _G] = getcoords(  _KEYREG   , _GROUP ,  _GROUP ) , out  =   matrix.get ( _VALS ,  _KEY ,  _G     )
export get (  matrix<string>   _VALS, matrix<string>  _KEYREG,   string _GROUP , int    _KEY    ) => [_K, _G] = getcoords(  _KEYREG   , _GROUP ,  _GROUP ) , out  =   matrix.get ( _VALS ,  _KEY ,  _G     )
export get (  matrix<linefill> _VALS, matrix<string>  _KEYREG,   string _GROUP , int    _KEY    ) => [_K, _G] = getcoords(  _KEYREG   , _GROUP ,  _GROUP ) , out  =   matrix.get ( _VALS ,  _KEY ,  _G     )
export get (  matrix<table>    _VALS, matrix<string>  _KEYREG,   string _GROUP , int    _KEY    ) => [_K, _G] = getcoords(  _KEYREG   , _GROUP ,  _GROUP ) , out  =   matrix.get ( _VALS ,  _KEY ,  _G     )
export get (  matrix<bool>     _VALS, matrix<string>  _KEYREG,   int    _GROUP , string _KEY    ) => _K       = getidx    ( matrix.col( _KEYREG,  _GROUP ) , _KEY ),  matrix.get ( _VALS ,  _K   ,  _GROUP )
export get (  matrix<box>      _VALS, matrix<string>  _KEYREG,   int    _GROUP , string _KEY    ) => _K       = getidx    ( matrix.col( _KEYREG,  _GROUP ) , _KEY ),  matrix.get ( _VALS ,  _K   ,  _GROUP )
export get (  matrix<color>    _VALS, matrix<string>  _KEYREG,   int    _GROUP , string _KEY    ) => _K       = getidx    ( matrix.col( _KEYREG,  _GROUP ) , _KEY ),  matrix.get ( _VALS ,  _K   ,  _GROUP )
export get (  matrix<float>    _VALS, matrix<string>  _KEYREG,   int    _GROUP , string _KEY    ) => _K       = getidx    ( matrix.col( _KEYREG,  _GROUP ) , _KEY ),  matrix.get ( _VALS ,  _K   ,  _GROUP )
export get (  matrix<int>      _VALS, matrix<string>  _KEYREG,   int    _GROUP , string _KEY    ) => _K       = getidx    ( matrix.col( _KEYREG,  _GROUP ) , _KEY ),  matrix.get ( _VALS ,  _K   ,  _GROUP )
export get (  matrix<label>    _VALS, matrix<string>  _KEYREG,   int    _GROUP , string _KEY    ) => _K       = getidx    ( matrix.col( _KEYREG,  _GROUP ) , _KEY ),  matrix.get ( _VALS ,  _K   ,  _GROUP )
export get (  matrix<line>     _VALS, matrix<string>  _KEYREG,   int    _GROUP , string _KEY    ) => _K       = getidx    ( matrix.col( _KEYREG,  _GROUP ) , _KEY ),  matrix.get ( _VALS ,  _K   ,  _GROUP )
export get (  matrix<string>   _VALS, matrix<string>  _KEYREG,   int    _GROUP , string _KEY    ) => _K       = getidx    ( matrix.col( _KEYREG,  _GROUP ) , _KEY ),  matrix.get ( _VALS ,  _K   ,  _GROUP )
export get (  matrix<linefill> _VALS, matrix<string>  _KEYREG,   int    _GROUP , string _KEY    ) => _K       = getidx    ( matrix.col( _KEYREG,  _GROUP ) , _KEY ),  matrix.get ( _VALS ,  _K   ,  _GROUP )
export get (  matrix<table>    _VALS, matrix<string>  _KEYREG,   int    _GROUP , string _KEY    ) => _K       = getidx    ( matrix.col( _KEYREG,  _GROUP ) , _KEY ),  matrix.get ( _VALS ,  _K   ,  _GROUP )

// @function get Grabs value and returns single item                                                                                                                                                                                                                                                    
// @param _VALS    Matrix Values slice
// @param _GROUP   name of group/category
// @param _KEY     name of item to fetch from value rregistry
export get (  matrix<bool>     _VALS,                            int    _GROUP , int    _KEY    ) =>  matrix.get( _VALS, _GROUP , _KEY)
export get (  matrix<box>      _VALS,                            int    _GROUP , int    _KEY    ) =>  matrix.get( _VALS, _GROUP , _KEY)
export get (  matrix<color>    _VALS,                            int    _GROUP , int    _KEY    ) =>  matrix.get( _VALS, _GROUP , _KEY)
export get (  matrix<float>    _VALS,                            int    _GROUP , int    _KEY    ) =>  matrix.get( _VALS, _GROUP , _KEY)
export get (  matrix<int>      _VALS,                            int    _GROUP , int    _KEY    ) =>  matrix.get( _VALS, _GROUP , _KEY)
export get (  matrix<label>    _VALS,                            int    _GROUP , int    _KEY    ) =>  matrix.get( _VALS, _GROUP , _KEY)
export get (  matrix<line>     _VALS,                            int    _GROUP , int    _KEY    ) =>  matrix.get( _VALS, _GROUP , _KEY)
export get (  matrix<linefill> _VALS,                            int    _GROUP , int    _KEY    ) =>  matrix.get( _VALS, _GROUP , _KEY)
export get (  matrix<table>    _VALS,                            int    _GROUP , int    _KEY    ) =>  matrix.get( _VALS, _GROUP , _KEY)
export get (  matrix<string>   _VALS,                            int    _GROUP , int    _KEY    ) =>  matrix.get( _VALS, _GROUP , _KEY)

// get group index number for matrix retrieval fronm valuematrix

// @function getgid
// @param _KEYREG Reg to pull group id from
// @param _GROUP  group index int, or string name to get the other missing type
export getgid( matrix<string> _KEYREG, string _GROUP                 )  => getidx(matrix.row(_KEYREG,0), _GROUP)
export getgid( matrix<string> _KEYREG, int    _GROUP                 )  => matrix.get(_KEYREG,0,_GROUP)

// @function getkid
// @param _KEYREG Reg to pull Key id from
// @param _GROUP  group index int, or string name 
// @param _KEY    index of string key id to get it's ID int
export getkid( matrix<string> _KEYREG, string _GROUP , string _KEY )    => getidx(matrix.col(_KEYREG, getgid(_KEYREG, _GROUP)),_KEY) 
export getkid( matrix<string> _KEYREG, int    _GROUP , string _KEY )    => getidx(matrix.col(_KEYREG, _GROUP),_KEY) 

// grab key by any string and number combination from registry
// @function getkey
// @param _KEYREG Reg to pull Key id from
// @param _GROUP  group index int, or string name for getting key string
// @param _KEY    index of string key id to get it's match of other type
export getkey( matrix<string> _KEYREG, string _GROUP , int    _KEY )    => get( _KEYREG, getgid(_KEYREG, _GROUP) , _KEY)
export getkey( matrix<string> _KEYREG, int    _GROUP , string _KEY )    => get( _KEYREG, _GROUP , getidx(matrix.col(_KEYREG, _GROUP),_KEY))
export getkey( matrix<string> _KEYREG, int    _GROUP , int    _KEY )    => get( _KEYREG, _GROUP , _KEY)
 

setitem(_VALMATRIX, _KEYREG,  _GROUP,  _KEY,  _value )     =>
    row    = matrix.row         ( _KEYREG    , 0     )
    group  = array.indexof      (  row       , array.includes ( row , _GROUP ) ?  _GROUP  : string   (na))
    matrix.set                  (  _KEYREG   , 0          , group   , _GROUP)                                     
    _checkrow                   (  _KEYREG   , _VALMATRIX , row     )
    col    = matrix.col         (  _KEYREG   , group )                                                 
    key    = array.indexof      (  col       , array.includes ( col , _KEY   ) ?  _KEY    : string  (na))
    matrix.set                  (  _KEYREG   , key        , group   , _KEY   )                                    
    _checkcol                   (  _KEYREG   , _VALMATRIX , col     )
    matrix.set                  ( _VALMATRIX , key,  group, _value  )
    

checkmissing(_missing,_VALS,_gid,_keyid) => _missing or  (not _missing and (matrix.rows(_VALS) < _keyid + 2 or matrix.columns(_VALS) < _gid + 2))

setInternal ( _VALS , _KEYREG , _GROUP , _KEY , _value ) =>  
    [_gid,_keyid] = getcoords(_KEYREG, _GROUP, _KEY)
    _missing = na(_gid) or na(_keyid) 
    // if key/group is new, create storage, else set to known location.
    if checkmissing(_missing,_VALS,_gid,_keyid)
        setitem   ( _VALS, _KEYREG, _GROUP, _KEY, _value) 
    else
        matrix.set(_VALS,_gid,_keyid,_value) 

// set to function
// @function set items to registry and chosen matrix container
// @param _VALS   Values matrix container
// @param _KEYREG Key registry
// @param _GROUP  (string) Group/Category name
// @param _KEY    (string) Key for item
// @param _value  item
// @returns void
export set ( matrix<bool>    _VALS,  matrix<string>  _KEYREG, string _GROUP , string _KEY   , bool     _value) => setInternal ( _VALS , _KEYREG , _GROUP , _KEY , _value ), getcoords(_KEYREG,  _GROUP, _KEY)
export set ( matrix<box>     _VALS,  matrix<string>  _KEYREG, string _GROUP , string _KEY   , box      _value) => setInternal ( _VALS , _KEYREG , _GROUP , _KEY , _value )
export set ( matrix<color>   _VALS,  matrix<string>  _KEYREG, string _GROUP , string _KEY   , color    _value) => setInternal ( _VALS , _KEYREG , _GROUP , _KEY , _value )
export set ( matrix<float>   _VALS,  matrix<string>  _KEYREG, string _GROUP , string _KEY   , float    _value) => setInternal ( _VALS , _KEYREG , _GROUP , _KEY , _value )
export set ( matrix<int>     _VALS,  matrix<string>  _KEYREG, string _GROUP , string _KEY   , int      _value) => setInternal ( _VALS , _KEYREG , _GROUP , _KEY , _value )
export set ( matrix<label>   _VALS,  matrix<string>  _KEYREG, string _GROUP , string _KEY   , label    _value) => setInternal ( _VALS , _KEYREG , _GROUP , _KEY , _value )
export set ( matrix<line>    _VALS,  matrix<string>  _KEYREG, string _GROUP , string _KEY   , line     _value) => setInternal ( _VALS , _KEYREG , _GROUP , _KEY , _value )
export set ( matrix<linefill>_VALS,  matrix<string>  _KEYREG, string _GROUP , string _KEY   , linefill _value) => setInternal ( _VALS , _KEYREG , _GROUP , _KEY , _value )
export set ( matrix<string>  _VALS,  matrix<string>  _KEYREG, string _GROUP , string _KEY   , string   _value) => setInternal ( _VALS , _KEYREG , _GROUP , _KEY , _value )
export set ( matrix<table>   _VALS,  matrix<string>  _KEYREG, string _GROUP , string _KEY   , table    _value) => setInternal ( _VALS , _KEYREG , _GROUP , _KEY , _value )

// delete item from registry and value from loaction,
// replaces with the na val used for detection of first empty slot

// @function del  grroup id
// @param _VALS    Matrix Values slice
// @param _KEYREG  Registry values matrix (strings)
// @param _GROUP   name of group/category
// @param _KEY     name of item to Delete frrom values and key
export del ( matrix<bool>     _VALS,  matrix<string>  _KEYREG,   string _GROUP , string _KEY    ) => [_K, _G] = getcoords( _KEYREG , _GROUP, _KEY ), matrix.set(_VALS, _K, _G, bool    (na)), matrix.set(_KEYREG, _K, _G, string(na))
export del ( matrix<box>      _VALS,  matrix<string>  _KEYREG,   string _GROUP , string _KEY    ) => [_K, _G] = getcoords( _KEYREG , _GROUP, _KEY ), matrix.set(_VALS, _K, _G, box     (na)), matrix.set(_KEYREG, _K, _G, string(na))
export del ( matrix<color>    _VALS,  matrix<string>  _KEYREG,   string _GROUP , string _KEY    ) => [_K, _G] = getcoords( _KEYREG , _GROUP, _KEY ), matrix.set(_VALS, _K, _G, color   (na)), matrix.set(_KEYREG, _K, _G, string(na))
export del ( matrix<float>    _VALS,  matrix<string>  _KEYREG,   string _GROUP , string _KEY    ) => [_K, _G] = getcoords( _KEYREG , _GROUP, _KEY ), matrix.set(_VALS, _K, _G, float   (na)), matrix.set(_KEYREG, _K, _G, string(na))
export del ( matrix<int>      _VALS,  matrix<string>  _KEYREG,   string _GROUP , string _KEY    ) => [_K, _G] = getcoords( _KEYREG , _GROUP, _KEY ), matrix.set(_VALS, _K, _G, int     (na)), matrix.set(_KEYREG, _K, _G, string(na))
export del ( matrix<label>    _VALS,  matrix<string>  _KEYREG,   string _GROUP , string _KEY    ) => [_K, _G] = getcoords( _KEYREG , _GROUP, _KEY ), matrix.set(_VALS, _K, _G, label   (na)), matrix.set(_KEYREG, _K, _G, string(na))
export del ( matrix<line>     _VALS,  matrix<string>  _KEYREG,   string _GROUP , string _KEY    ) => [_K, _G] = getcoords( _KEYREG , _GROUP, _KEY ), matrix.set(_VALS, _K, _G, line    (na)), matrix.set(_KEYREG, _K, _G, string(na))
export del ( matrix<linefill> _VALS,  matrix<string>  _KEYREG,   string _GROUP , string _KEY    ) => [_K, _G] = getcoords( _KEYREG , _GROUP, _KEY ), matrix.set(_VALS, _K, _G, linefill(na)), matrix.set(_KEYREG, _K, _G, string(na))
export del ( matrix<table>    _VALS,  matrix<string>  _KEYREG,   string _GROUP , string _KEY    ) => [_K, _G] = getcoords( _KEYREG , _GROUP, _KEY ), matrix.set(_VALS, _K, _G, table   (na)), matrix.set(_KEYREG, _K, _G, string(na))
export del ( matrix<string>   _VALS,  matrix<string>  _KEYREG,   string _GROUP , string _KEY    ) => [_K, _G] = getcoords( _KEYREG , _GROUP, _KEY ), matrix.set(_VALS, _K, _G, string  (na)), matrix.set(_KEYREG, _K, _G, string(na))

// =========================================================
detach_internal(_val, _GROUP,_KEY,_VALUE) =>
    var _KEYREG = initRegistry()
    set (_val ,  _KEYREG, _GROUP,_KEY,_VALUE)
    [_KEYREG, _val]

// start a new registry and a single matrix along with it, autotypified and given first value.
// @function detached make detached registry/val matrix 
// @param _GROUP    Name of first group
// @param _KEY   Name of first item
// @param _VALUE  Item of any type, sets the output type too.
// @returns [new key registry, initial values matrix, id of initial group, id of first key]
export detached(string _GROUP, string _KEY, bool      _VALUE ) =>  _vals = newbool    () ,  [_r,_v] = detach_internal( _vals, _GROUP, _KEY, _VALUE)  , [_g,_k] =getcoords(_r, _GROUP, _KEY), [_r,_v,_g,_k]
export detached(string _GROUP, string _KEY, box       _VALUE ) =>  _vals = newbox     () ,  [_r,_v] = detach_internal( _vals, _GROUP, _KEY, _VALUE)  , [_g,_k] =getcoords(_r, _GROUP, _KEY), [_r,_v,_g,_k]
export detached(string _GROUP, string _KEY, color     _VALUE ) =>  _vals = newcolor   () ,  [_r,_v] = detach_internal( _vals, _GROUP, _KEY, _VALUE)  , [_g,_k] =getcoords(_r, _GROUP, _KEY), [_r,_v,_g,_k]
export detached(string _GROUP, string _KEY, float     _VALUE ) =>  _vals = newfloat   () ,  [_r,_v] = detach_internal( _vals, _GROUP, _KEY, _VALUE)  , [_g,_k] =getcoords(_r, _GROUP, _KEY), [_r,_v,_g,_k]
export detached(string _GROUP, string _KEY, int       _VALUE ) =>  _vals = newint     () ,  [_r,_v] = detach_internal( _vals, _GROUP, _KEY, _VALUE)  , [_g,_k] =getcoords(_r, _GROUP, _KEY), [_r,_v,_g,_k]
export detached(string _GROUP, string _KEY, label     _VALUE ) =>  _vals = newlabel   () ,  [_r,_v] = detach_internal( _vals, _GROUP, _KEY, _VALUE)  , [_g,_k] =getcoords(_r, _GROUP, _KEY), [_r,_v,_g,_k]
export detached(string _GROUP, string _KEY, line      _VALUE ) =>  _vals = newline    () ,  [_r,_v] = detach_internal( _vals, _GROUP, _KEY, _VALUE)  , [_g,_k] =getcoords(_r, _GROUP, _KEY), [_r,_v,_g,_k]
export detached(string _GROUP, string _KEY, linefill  _VALUE ) =>  _vals = newlinefill() ,  [_r,_v] = detach_internal( _vals, _GROUP, _KEY, _VALUE)  , [_g,_k] =getcoords(_r, _GROUP, _KEY), [_r,_v,_g,_k]
export detached(string _GROUP, string _KEY, string    _VALUE ) =>  _vals = newstring  () ,  [_r,_v] = detach_internal( _vals, _GROUP, _KEY, _VALUE)  , [_g,_k] =getcoords(_r, _GROUP, _KEY), [_r,_v,_g,_k]
export detached(string _GROUP, string _KEY, table     _VALUE ) =>  _vals = newtable   () ,  [_r,_v] = detach_internal( _vals, _GROUP, _KEY, _VALUE)  , [_g,_k] =getcoords(_r, _GROUP, _KEY), [_r,_v,_g,_k]
    


// // ============================================================================
// //    ======================  DEMO  ===========================
// //    a few uses, there is ar more that can be done
// //    ie: a sepearate4 key registry for each ticker and multiportfolio management
// //    it's a low level tool, so there's raelly a mountain of options
// //    the setting/getting by name is mainly for passing globals into functions
// //    however within a local block, best to use the GID/KEYID for direct get/set

// //  init a registry for global
// varip _KEYREG     = initRegistry  ()

// // init matrixes to hold different types of data
// var   _boolvals  = newbool        ( )
// var   _floatvals = newfloat       ( )
// var   _mtx_lines  = newline        ( )
// var   _mtx_boxes  = newbox         ( )
// var   _mtx_fills  = newlinefill    ( )

// if barstate.islastconfirmedhistory
//     for i = 1 to 5
//         _linetesta =  line.new(last_bar_index - 5*i                , close[5* i]           , last_bar_index ,  close)
//         _linetestb =  line.new(last_bar_index - math.floor(5*i*i-i), close[5* i+1]         , last_bar_index ,  close)
//         _linefill  =  linefill.new(_linetesta, _linetestb, color.new(color.aqua,90))


//         set(_mtx_lines  , _KEYREG, 'Line A', str.tostring(i) +' line A',  _linetesta )
//         set(_mtx_lines  , _KEYREG, 'Line B', str.tostring(i) +' line B',  _linetestb )
//         set(_mtx_fills  , _KEYREG, 'Fills ', str.tostring(i) +' Fill  ',  _linefill  )

//     set ( _boolvals, _KEYREG, 'boxes', 'boolbox' ,  true )
//     set ( _mtx_boxes , _KEYREG, 'boxes', 'boolbox' , box.new(time[10], math.max(high,high[10]), time, math.min(low,low[100]), text_color = color.white, bgcolor = color.new(color.black,90),
//                          text =  'Mite Tricks', xloc=xloc.bar_time, border_style=line.style_dashed))

// // // ===============================================================

// // //   OTHER DEMO...

// mtf(x) => request.security(syminfo.tickerid, '15', x)

// /// example 2... cqan be expanded on vastly
// // .. or  as far as pine script will take you.

// _ohlcreg      = initRegistry()

// //some mtx slices
// _regfloats    = newfloat()
// _hist1_floats = newfloat()
// _colorreg     = newcolor()

// var _MTFSTR   = 'MTF'
// var _REGSTR   = 'Regular'
// var _openSTR  = 'open'
// var _highSTR  = 'high'
// var _lowSTR   = 'low'
// var _closeSTR = 'close'

// set(_regfloats   ,  _ohlcreg, _REGSTR , _openSTR   ,  open  )
// set(_regfloats   ,  _ohlcreg, _REGSTR , _highSTR   ,  high  )
// set(_regfloats   ,  _ohlcreg, _REGSTR , _lowSTR    ,  low   )
// set(_regfloats   ,  _ohlcreg, _REGSTR , _closeSTR  ,  close )
// set(_regfloats   ,  _ohlcreg, _MTFSTR , _openSTR   ,  mtf(open  ))
// set(_regfloats   ,  _ohlcreg, _MTFSTR , _highSTR   ,  mtf(high  ))
// set(_regfloats   ,  _ohlcreg, _MTFSTR , _lowSTR    ,  mtf(low   ))
// set(_regfloats   ,  _ohlcreg, _MTFSTR , _closeSTR  ,  mtf(close ))
// set(_hist1_floats,  _ohlcreg, _REGSTR , _openSTR   ,  open  [1])
// set(_hist1_floats,  _ohlcreg, _REGSTR , _highSTR   ,  high  [1])
// set(_hist1_floats,  _ohlcreg, _REGSTR , _lowSTR    ,  low   [1])
// set(_hist1_floats,  _ohlcreg, _REGSTR , _closeSTR  ,  close [1])
// set(_hist1_floats,  _ohlcreg, _MTFSTR , _openSTR   ,  mtf(open [1] ))
// set(_hist1_floats,  _ohlcreg, _MTFSTR , _highSTR   ,  mtf(high [1] ))
// set(_hist1_floats,  _ohlcreg, _MTFSTR , _lowSTR    ,  mtf(low  [1] ))
// set(_hist1_floats,  _ohlcreg, _MTFSTR , _closeSTR  ,  mtf(close[1] ))

// // add colors for these specific ones.. if a value is attempted to retrieve
// //  but the spot on the value matrix is empty, it will siimple pull a typecast na.
// // so these colors show when specidfied.. will have to make a global or a '*' for any'
// //  you can have multiple overlapping key regiustries, say each with a differnt tite for the groups andcategories..
// // write into one key registry and pull up by other names and titles to another key registry.
 
// set(_colorreg    ,  _ohlcreg, _REGSTR, _openSTR  ,  color.red   )
// set(_colorreg    ,  _ohlcreg, _REGSTR, _highSTR  ,  color.green )
// set(_colorreg    ,  _ohlcreg, _REGSTR, _lowSTR   ,  color.blue  )
// set(_colorreg    ,  _ohlcreg, _REGSTR, _closeSTR ,  color.orange)

// set(_colorreg    ,  _ohlcreg, _MTFSTR, _openSTR  ,  color.fuchsia   )
// set(_colorreg    ,  _ohlcreg, _MTFSTR, _highSTR  ,  color.lime )
// set(_colorreg    ,  _ohlcreg, _MTFSTR, _lowSTR   ,  color.aqua  )
// set(_colorreg    ,  _ohlcreg, _MTFSTR, _closeSTR ,  color.yellow)

// // plot those 4..
// plot(get(_regfloats,_ohlcreg, _REGSTR, _openSTR ), 'Normal open  ' , get(_colorreg , _ohlcreg, _REGSTR, _openSTR))
// plot(get(_regfloats,_ohlcreg, _REGSTR, _highSTR ), 'Normal high  ' , get(_colorreg , _ohlcreg, _REGSTR, _highSTR))
// plot(get(_regfloats,_ohlcreg, _REGSTR, _lowSTR  ), 'Normal low   ' , get(_colorreg , _ohlcreg, _REGSTR, _lowSTR ))
// plot(get(_regfloats,_ohlcreg, _REGSTR, _closeSTR), 'Normal close ' , get(_colorreg , _ohlcreg, _REGSTR, _closeSTR))


// // or select one amongst them all for switchng around..
// // the retrieval now can select along any axis... 
// //     which matrix to use
// valmatrix = switch input.int(0,'Pick Matrix slice, reg/hist')
//     0 => _regfloats
//     1 => _hist1_floats
 
// ///     which group to pull from
// _barchoice = input.string(_REGSTR, 'MTF or REg', options = [_REGSTR,_MTFSTR])

// ///     which value from that group-.
// valuechoice = switch input.int(1,'Val O/H/L/C',1,4)
//     1 => _openSTR
//     2 => _highSTR
//     3 => _lowSTR 
//     4 => _closeSTR
     
// plot(get(valmatrix , _ohlcreg,  _barchoice  , valuechoice), ' chosenval', get(_colorreg , _ohlcreg, _barchoice  , valuechoice),2)

// import kaigouthro/matrixautotable/9 as mtb
// mtb.matrixtable(_KEYREG      , tableYpos = 'bottom', tableXpos = 'right' )
// mtb.matrixtable(_regfloats   ,_ohlcreg, _colorreg,  tableYpos = 'bottom', tableXpos = 'center')
