// Copyright (C) 2021 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use size file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import {exists} from '../base/utils';

export type Key = string|number;

export interface ArgNode<T> {
  key: Key;
  value?: T;
  children?: ArgNode<T>[];
}

// Arranges a flat list of arg-like objects (objects with a string "key" value
// indicating their path) into a nested tree.
//
// This process is relatively forgiving as it allows nodes with both values and
// child nodes as well as children with mixed key types in the same node.
//
// When duplicate nodes exist, the latest one is picked.
//
// If you want to convert args to a POJO, try convertArgsToObject().
//
// Key should be a path seperated by periods (.) or indexes specified using a
// number inside square brackets.
// e.g. foo.bar[0].x
//
// See unit tests for examples.
export function convertArgsToTree<T extends {key: string}>(input: T[]):
    ArgNode<T>[] {
  const result: ArgNode<T>[] = [];
  for (const arg of input) {
    const {key} = arg;
    const nestedKey = getNestedKey(key);
    insert(result, nestedKey, key, arg);
  }
  return result;
}

function getNestedKey(key: string): Key[] {
  const result: Key[] = [];
  let match;
  const re = /([^\.\[\]]+)|\[(\d+)\]/g;
  while ((match = re.exec(key)) !== null) {
    result.push(match[2] ? parseInt(match[2]) : match[1]);
  }
  return result;
}

function insert<T>(
    args: ArgNode<T>[], keys: Key[], path: string, value: T): void {
  const currentKey = keys.shift()!;
  let node = args.find((x) => x.key === currentKey);
  if (!node) {
    node = {key: currentKey};
    args.push(node);
  }
  if (keys.length > 0) {
    if (node.children === undefined) {
      node.children = [];
    }
    insert(node.children, keys, path, value);
  } else {
    node.value = value;
  }
}

type ArgLike<T> = {
  key: string,
  value: T
};
type ObjectType<T> = T|ObjectType<T>[]|{[key: string]: ObjectType<T>};

// Converts a list of argument-like objects (i.e. objects with key and value
// fields) to a POJO.
//
// This function cannot handle cases where nodes contain mixed node types (i.e.
// both number and string types) as nodes cannot be both an object and an array,
// and will throw when this situation arises.
//
// Key should be a path seperated by periods (.) or indexes specified using a
// number inside square brackets.
// e.g. foo.bar[0].x
//
// See unit tests for examples.
export function convertArgsToObject<A extends ArgLike<T>, T>(input: A[]):
    ObjectType<T> {
  const nested = convertArgsToTree(input);
  return parseNodes(nested);
}

function parseNodes<A extends ArgLike<T>, T>(nodes: ArgNode<A>[]):
    ObjectType<T> {
  if (nodes.every(({key}) => typeof key === 'string')) {
    const dict: ObjectType<T> = {};
    for (const node of nodes) {
      if (node.key in dict) {
        throw new Error(`Duplicate key ${node.key}`);
      }
      dict[node.key] = parseNode(node);
    }
    return dict;
  } else if (nodes.every(({key}) => typeof key === 'number')) {
    const array: ObjectType<T>[] = [];
    for (const node of nodes) {
      const index = node.key as number;
      if (index in array) {
        throw new Error(`Duplicate array index ${index}`);
      }
      array[index] = parseNode(node);
    }
    return array;
  } else {
    throw new Error('Invalid mix of node key types');
  }
}

function parseNode<A extends ArgLike<T>, T>({value, children}: ArgNode<A>):
    ObjectType<T> {
  if (exists(value) && !exists(children)) {
    return value.value;
  } else if (!exists(value) && exists(children)) {
    return parseNodes(children);
  } else {
    throw new Error('Invalid node type');
  }
}
