"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateModelViewService = generateModelViewService;
exports.generateModelViewService_NoRepository = generateModelViewService_NoRepository;
const Generator = __importStar(require("@postxl/generator"));
function generateModelViewService({ model, context }) {
    const imports = Generator.ImportGenerator.from(model.view.service.location);
    imports.addType(model.types);
    imports.addType({ name: Generator.toTypeName('User'), location: context.types.location });
    imports.addType(model.types.id);
    imports.add(context.view.service);
    if (model.repository.kind === 'NoRepository') {
        return generateModelViewService_NoRepository({ model, context, imports });
    }
    else {
        return generateModelViewService_HasRepository({ model, context, imports });
    }
}
function generateModelViewService_HasRepository({ model, context, imports, }) {
    if (model.repository.kind === 'NoRepository') {
        return '';
    }
    imports.add(model.repository);
    return `
import { Inject, Injectable, forwardRef } from '@nestjs/common'

${imports.generate()}

@Injectable()
export class ${model.view.service.name} {
  constructor(
    public readonly data: ${model.repository.name},
    @Inject(forwardRef(() => ${context.view.service.name})) 
        private readonly viewService: ${context.view.service.name},
  ) {}

  /**
   * Returns the raw ${model.userFriendlyName} with the given id or null if it does not exist.
   * Raw: The ${model.userFriendlyName} only contains linked Ids, not the linked items themselves.
   */
  public async get({ id, user }: { id: ${model.types.id.name}, user: User }): Promise<${model.types.name} | null> {
    const item = await this.data.get(id)
    if (!item) {
      return null
    }

    await this.authorize({ item, user })

    return item
  }

  /**
   * Returns a map of all ${model.userFriendlyNamePlural}.
   */
  public async getAll(user: User): Promise<Map<${model.types.id.name}, ${model.types.name}>> {
        const result = await this.data.getAll()

        // Removing non-authorized items from the result.
        for (const [key, value] of result.entries()) {
          try {
            await this.authorize({ item: value, user })
          } catch {
            result.delete(key)
          }
        }
    
        return result
  }

  /**
   * Returns a list of all ${model.userFriendlyNamePlural}.
   */
  public async getList(user: User): Promise<${model.types.name}[]> {
        const result: ${model.types.name}[] = []

        // Removing non-authorized items from the result.
        for (const item of (await this.data.getAll()).values()) {
          try {
            await this.authorize({ item, user })
            result.push(item)
          } catch {
            // Do nothing.
          }
        }
    
        return result
  }
  ${generateAuthorizeMethod({ model, context })}
}
`;
}
function generateModelViewService_NoRepository({ model, context, imports, }) {
    if (model.repository.kind !== 'NoRepository') {
        return '';
    }
    // imports.addImports({
    //   [model.types.importPath]: [toAnnotatedTypeName(toTypeName('User'))],
    // })
    return `
/* eslint-disable @typescript-eslint/no-unused-vars */
import z from 'zod'

import { Inject, Injectable, forwardRef } from '@nestjs/common'

${imports.generate()}

@Injectable()
export class ${model.view.service.name} {
  constructor(
    @Inject(forwardRef(() => ${context.view.service.name})) 
        private readonly viewService: ${context.view.service.name},
  ) {}

  /**
   * Returns the raw ${model.userFriendlyName} with the given id or null if it does not exist.
   * Raw: The ${model.userFriendlyName} only contains linked Ids, not the linked items themselves.
   */
  public async get({ id, user }: { id: ${model.types.id.name}, user: User }): Promise<${model.types.name} | null> {
  
    // TODO: Implement this method.  
    const item = await Promise.resolve(null) // NOSONAR - adhere to the same interface
      
    if (!item) {
      return null
    }

    await this.authorize({ item, user })

    return item
  }

  /**
   * Returns a map of all ${model.userFriendlyNamePlural}.
   */
  public async getAll(user: User): Promise<Map<${model.types.id.name}, ${model.types.name}>> {
        // TODO: Implement this method.
        const result = await Promise.resolve(new Map()) // NOSONAR - adhere to the same interface

        // Removing non-authorized items from the result.
        for (const [key, value] of result.entries()) {
          try {
            await this.authorize({ item: value, user })
          } catch (e) {
            result.delete(key)
          }
        }
    
        return result
  }

  ${generateAuthorizeMethod({ model, context })}
}`;
}
function generateAuthorizeMethod({ model }) {
    return `/**
  * Authorizes access to ${model.userFriendlyName}.
  */
  public async authorize({ item: _item, user: _user}: { item: ${model.types.name}, user: User }): Promise<void> {
    // TODO: Implement authorization logic here.
    return Promise.resolve() // NOSONAR - adhere to the same interface
  }`;
}
//# sourceMappingURL=model-view-service.generator.js.map