/* eslint-disable @typescript-eslint/ban-types */
/*
 * Copyright (C) 2020-2021 StApps
 * This program is free software: you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <https://www.gnu.org/licenses/>.
 */

import {Injectable} from '@angular/core';

/* eslint-disable @typescript-eslint/member-ordering, class-methods-use-this */

export abstract class ThingTranslateParser {
  /**
   * Gets a value from an object given a keyPath
   * parser.getValueFromKeyPath(anObject, 'property.subarray[42].etc');
   */
  abstract getValueFromKeyPath(instance: object, keyPath: string): unknown;
}

@Injectable()
export class ThingTranslateDefaultParser extends ThingTranslateParser {
  getValueFromKeyPath(instance: object, keyPath: string): unknown {
    // keyPath = aproperty[0].anotherproperty["arrayproperty"][42].finalproperty
    let path = keyPath.replaceAll(/["']'"/gim, '.');
    // path = aproperty[0].anotherproperty[.arrayproperty.][42].finalproperty
    path = path.replaceAll(/[\[\]]/gim, '.');
    // path = aproperty.0..anotherproperty..arrayproperty...42..finalproperty
    // TODO
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    path = path.replaceAll(/\.{2,}/gim, '.');
    // path = aproperty.0.anotherproperty.arrayproperty.42.finalproperty

    const keyPathChain = keyPath.split('.');

    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    let property = instance as any;

    for (const key of keyPathChain) {
      property = property[key] ?? undefined;
    }

    return property;
  }
}

/**
 * TODO
 */
export function isDefined<T>(value?: T | null): value is T {
  return value !== undefined && value !== null;
}
