
export interface ModelDefinition {
  name: string;
  plural: string;
  path?: string;
  idName?: string;
  properties: {
    [k: string]: {
      name: string,
      type: string,
      default?: any
    }
  };
  relations?: {
    [k: string]: {
      name: string,
      type: string,
      model: string,
      relationType?: string,
      modelThrough?: string,
      keyThrough?: string,
      keyFrom?: string,
      keyTo?: string
    }
  };
}

declare var Object: any;
type LoopbackTypes = string | number | boolean | Date

type LoopbackOps =
  'eq'
  | 'and'
  | 'or'
  | 'gt'
  | 'gte'
  | 'lt'
  | 'lte'
  | 'between'
  | 'inq'
  | 'nin'
  | 'neq'
  | 'like'
  | 'nlike'
  | 'options'
  | 'regexp';

type LoopbackWhereOperation = {
  [op in LoopbackOps]: LoopbackTypes | LoopbackTypes[];
};

interface BaseLoopbackWhere {
  [field: string]: LoopbackTypes | LoopbackWhereOperation | LoopbackAndOrWhere;
}

type LoopbackAndOrWhere = {
  [op in 'and' | 'or']: BaseLoopbackWhere[];
}

type LoopbackWhere = BaseLoopbackWhere | LoopbackAndOrWhere;

export interface LoopbackInclude {
  relation: string;
  scope?: LoopBackFilter
}

export interface LoopBackFilter {
  fields?: string[] | { [field: string]: boolean };
  include?: string | string[] | LoopbackInclude | LoopbackInclude[];
  limit?: number;
  order?: string | string[];
  skip?: number;
  offset?: any;
  where?: LoopbackWhere;
}

export interface AccessTokenInterface {
  id?: string;
  ttl?: number;
  scopes?: ['string'];
  created?: Date;
  userId?: string;
  user?: any;
}

export class AccessToken implements AccessTokenInterface {
  id: string;
  ttl: number;
  scopes: ['string'];
  created: Date;
  userId: string;
  user: any;
  constructor(data?: AccessTokenInterface) {
    Object.assign(this, data);
  }

  /**
   * The name of the model represented by this $resource,
   * i.e. `AccessToken`.
   */
  public static getModelName(): string {
    return 'AccessToken';
  }

  /**
   * @method factory
   * @author Jonathan Casarrubias
   * @license MIT
   * This method creates an instance of AccessToken for dynamic purposes.
   */
  public static factory(data: AccessTokenInterface): AccessToken{
    return new AccessToken(data);
  }

  /**
   * @method getModelDefinition
   * @author Julien Ledun
   * @license MIT
   * This method returns an object that represents some of the model
   * definitions.
   */
  public static getModelDefinition(): ModelDefinition {
    return {
      name: 'AccessToken',
      plural: 'AccessTokens',
      properties: {
        id: {
          name: 'id',
          type: 'string'
        },
        ttl: {
          name: 'ttl',
          type: 'number',
          default: 1209600
        },
        scopes: {
          name: 'scopes',
          type: `['string']`
        },
        created: {
          name: 'created',
          type: 'Date'
        },
        userId: {
          name: 'userId',
          type: 'string'
        },
      },
      relations: {
        user: {
          name: 'user',
          type: 'User',
          model: 'User'
        },
      }
    };
  }
}

export class SDKToken implements AccessTokenInterface {
  id: any = null;
  ttl: number;
  scopes: any = null;
  created: any = null;
  userId: any = null;
  user: any = null;
  rememberMe = false;
  constructor(data?: AccessTokenInterface) {
    Object.assign(this, data);
  }
}

/**
 * This GeoPoint represents both, LoopBack and MongoDB GeoPoint
 */
export interface GeoPoint  {
    lat?: number;
    lng?: number;
    type?: string;
    coordinates?: number[];
}

export interface StatFilter {
    range: string;
    custom?: {
      start: string,
      end: string
    };
    where?: {};
    groupBy?: string;
}
