// 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');
  }
}
