// 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 {isString} from '../base/object_utils';
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}) => isString(key))) {
    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');
  }
}
