/**
 * Implement this interface in each of your entity models
 */
export interface Entity {}

/**
 * Arbitrary type for json objects
 */
export type JSONObject =
    | null
    | string
    | number
    | boolean
    | { [x: string]: JSONObject }
    | Array<JSONObject>

/**
 * Parses the object and returns only its associated data, useful for json objects fetched from a server request
 * @param json object
 * @returns Json with the requested data
 */
export function parse(json: any): any {
    return JSON.parse(JSON.stringify(json)).data
}

/**
 * Returns an instance of a given model from a json object
 * @param value Json object
 * @param clazz Model to parse from the json object
 * @returns Model instance
 */
export function jsonObjectToEntity<T extends Entity>(value: JSONObject, clazz: { new (): T }): T {
    return Object.assign(new clazz(), value)
}

/**
 * Returns a list of instances of a given model from a json object
 * @param values Json object
 * @param clazz Model to parse from the json object
 * @returns Model instances
 */
export function jsonObjectToEntities<T extends Entity>(values: JSONObject[], clazz: { new (): T }): T[] {
    const entities: Array<T> = new Array(0)
    for (const item of values) {
        entities.push(jsonObjectToEntity(item, clazz))
    }
    return entities
}