
type arrayLoc = [number, number, number, number];
type baseLoc = arrayLoc | Element;
type baseObjLoc = { id: any, loc: baseLoc };
type loc = baseLoc | baseObjLoc;

type simpleSquares = Array<loc>;

type subLocs = {
  locs: simpleSquares;
  wrap: loc;
  subs?: subLocs;
  loop?: "row" | "col";
};

type objSquares = {
  locs: Array<loc>;
  subs?: subLocs | Array<subLocs>;
  loop?: "row" | "col";
};

type arySquares = Array<subLocs>;

type directionLoc = baseObjLoc;

interface Options {
  memo?: boolean;
  scroll?: boolean;
  fuzzy?: boolean;
}

type memoReturn = {
  left(id: any): directionLoc
  right(id: any): directionLoc
  up(id: any): directionLoc
  down(id: any): directionLoc
  update(id: any, newRects: subLocs)
  more(id: any, newRects: subLocs)
}

type scrollOpts = {
  fuzzy?: boolean
  momentCache?: boolean
}

type scrollReturn = {
  scroll(newRects: { id: any, loc: arrayLoc }): void
  left(id: any, opts: scrollOpts): directionLoc
  right(id: any, opts: scrollOpts): directionLoc
  up(id: any, opts: scrollOpts): directionLoc
  down(id: any, opts: scrollOpts): directionLoc
  update(id: any, newRects: subLocs)
  more(id: any, newRects: subLocs)
}

type simpleReturn = Map<any, { up?: directionLoc; down?: directionLoc; left?: directionLoc; right?: directionLoc }>

declare function naviix(squares: simpleSquares | objSquares | arySquares, options?: Options):
  simpleReturn | memoReturn | scrollReturn;

export = naviix;
export default naviix;