import lodash from 'lodash';

import { Acl } from '../../../../../interface/config';
import BaseRender from '../../BaseRender';

class ExpressXcMiddleware extends BaseRender {
  /**
   *
   * @param dir
   * @param filename
   * @param ctx
   * @param ctx.tn
   * @param ctx.columns
   * @param ctx.relations
   */
  constructor({ dir, filename, ctx }) {
    super({ dir, filename, ctx });
  }

  /**
   *  Prepare variables used in code template
   */
  prepare() {
    let data: any = {};

    /* example of simple variable */
    data = this.ctx;

    /* for complex code provide a func and args - do derivation within the func cbk */
    data.hasMany = {
      func: this._renderXcHasManyRoutePermissions.bind(this),
      args: {
        tn: this.ctx.tn,
        columns: this.ctx.columns,
        hasMany: this.ctx.hasMany,
        relations: this.ctx.relations,
        routeVersionLetter: this.ctx.routeVersionLetter
      }
    };

    /* for complex code provide a func and args - do derivation within the func cbk */
    data.belongsTo = {
      func: this._renderXcBelongsToRoutePermissions.bind(this),
      args: {
        dbType: this.ctx.dbType,
        tn: this.ctx.tn,
        columns: this.ctx.columns,
        belongsTo: this.ctx.belongsTo,
        relations: this.ctx.relations,
        routeVersionLetter: this.ctx.routeVersionLetter
      }
    };

    return data;
  }

  private _renderXcHasManyRoutePermissions(args) {
    let str = '';
    let hmRelations = args.relations
      ? args.relations.filter(r => r.rtn === args.tn)
      : [];
    if (hmRelations.length > 1)
      hmRelations = lodash.uniqBy(hmRelations, function(e) {
        return [e.tn, e.rtn].join();
      });
    for (let i = 0; i < hmRelations.length; ++i) {
      str += `
        '/api/${args.routeVersionLetter}1/${args.tn}/has/${hmRelations[i].tn}' : {get:{admin:true,user:true,guest:true}},
        '/api/${args.routeVersionLetter}1/${args.tn}/:parentId/${hmRelations[i].tn}' : {get:{admin:true,user:true,guest:true},post:{admin:true,user:true,guest:true}},
        '/api/${args.routeVersionLetter}1/${args.tn}/:parentId/${hmRelations[i].tn}/findOne' : {get:{admin:true,user:true,guest:true}},
        '/api/${args.routeVersionLetter}1/${args.tn}/:parentId/${hmRelations[i].tn}/count' : {get:{admin:true,user:true,guest:true}},
        '/api/${args.routeVersionLetter}1/${args.tn}/:parentId/${hmRelations[i].tn}/:id' : {get:{admin:true,user:true,guest:true},put:{admin:true,user:true,guest:true},delete:{admin:true,user:true,guest:true}},
        '/api/${args.routeVersionLetter}1/${args.tn}/:parentId/${hmRelations[i].tn}/:id/exists' : {get:{admin:true,user:true,guest:true}},
      `;
    }

    return str;

    /* iterate over has many relations */
  }

  _renderXcBelongsToRoutePermissions(args) {
    let str = '';
    //
    let btRelations = args.relations
      ? args.relations.filter(r => r.tn === args.tn)
      : [];
    if (btRelations.length > 1)
      btRelations = lodash.uniqBy(btRelations, function(e) {
        return [e.tn, e.rtn].join();
      });
    for (let i = 0; i < btRelations.length; ++i) {
      str += `'/api/${args.routeVersionLetter}1/${args.tn}/belongs/:parents' : {get:{admin:true,user:true,guest:true}},`;
    }
    return str;
  }

  getObject(): Acl {
    return {
      creator: {
        read: true,
        ...(this.ctx.type !== 'view'
          ? {
              create: true,
              update: true,
              delete: true
            }
          : {})
      },
      editor: {
        read: true,
        ...(this.ctx.type !== 'view'
          ? {
              create: true,
              update: true,
              delete: true
            }
          : {})
      },
      commenter: {
        read: true,
        ...(this.ctx.type !== 'view'
          ? {
              create: false,
              update: false,
              delete: false
            }
          : {})
      },
      viewer: {
        read: true,
        ...(this.ctx.type !== 'view'
          ? {
              create: false,
              update: false,
              delete: false
            }
          : {})
      },
      guest: {
        read: false,
        ...(this.ctx.type !== 'view'
          ? {
              create: false,
              update: false,
              delete: false
            }
          : {})
      }
    };
  }
}

export default ExpressXcMiddleware;
