"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.GeocoderService = exports.GeocoderResult = exports.GeocoderLocation = void 0;
const tslib_1 = require("tslib");
/* eslint-disable @typescript-eslint/naming-convention */
const core_1 = require("@loopback/core");
const moment_1 = tslib_1.__importDefault(require("moment"));
const generated_response_1 = require("../../helper/generated-response");
const method_value_result_1 = require("../../helper/method-value-result");
const entity_name_1 = require("../../models/entity-name");
const action_entity_service_1 = require("../../services/action-entity/action-entity.service");
const object_tree_const_1 = require("../../services/object-tree/object-tree.const");
const server_config_service_1 = require("../server-config/server-config.service");
const application_error_1 = require("./../../helper/application-error");
const method_value_result_2 = require("./../../helper/method-value-result");
const transient_entity_service_1 = require("./../../services/transient-entity/transient-entity.service");
const cached_result_service_1 = require("./../cached-result/cached-result.service");
const web_site_const_1 = require("./../web-site/web-site.const");
const geocoder_const_1 = require("./geocoder.const");
class GeocoderLocation extends method_value_result_2.MethodValueSimpleJsonResult {
}
exports.GeocoderLocation = GeocoderLocation;
class GeocoderResult extends method_value_result_1.SimpleMethodValueResult {
    buildDisplayedValue(jsonResult) {
        let lines = super.buildDisplayedValue(jsonResult);
        lines += `
    <div class="mapouter">
      <div class="gmap_canvas">
        <iframe width="100%" height="318" id="gmap_canvas" src="https://maps.google.com/maps?q=${jsonResult.latitude},${jsonResult.longitude}&t=&z=15&ie=UTF8&iwloc=&output=embed" frameborder="0" scrolling="no" marginheight="0" marginwidth="0">
        </iframe>
        <style>
          .mapouter{position:relative;text-align:right;height:318px;width:100%px;}
        </style>
        <style>
          .gmap_canvas {overflow:hidden;background:none!important;height:318px;width:100%px;}
        </style>
      </div>
    </div>
    `;
        return lines;
    }
}
exports.GeocoderResult = GeocoderResult;
let GeocoderService = class GeocoderService {
    constructor(serverConfigService, actionEntityService, cachedResultService, transientEntityService) {
        this.serverConfigService = serverConfigService;
        this.actionEntityService = actionEntityService;
        this.cachedResultService = cachedResultService;
        this.transientEntityService = transientEntityService;
        this.services = [];
        this.actionEntityService.registerNewViewFunction(geocoder_const_1.GEOCODER_PROVIDER, GeocoderService.name, 'Geocoder an address', entity_name_1.EntityName.objectNode, 'geocode', object_tree_const_1.TENANT_TYPE.name, this.geocodeTenantNode.bind(this), 'create');
        this.actionEntityService.registerNewViewFunction(geocoder_const_1.GEOCODER_PROVIDER, GeocoderService.name, 'Geocoder an address', entity_name_1.EntityName.objectNode, 'geocode', web_site_const_1.WEB_SITE_VIEW_TYPE.name, this.geocodeTenantNode.bind(this), 'create');
        this.actionEntityService.registerNewMethodFunction(geocoder_const_1.GEOCODER_PROVIDER, GeocoderService.name, 'Geocoder an address', entity_name_1.EntityName.objectNode, 'geocode', web_site_const_1.WEB_SITE_VIEW_TYPE.name, this.geocodeTenantNodeFromPostOrTree.bind(this), 'create');
        this.actionEntityService.registerNewMethodFunction(geocoder_const_1.GEOCODER_PROVIDER, GeocoderService.name, 'Geocoder an address', entity_name_1.EntityName.objectTree, 'geocode', web_site_const_1.WEB_SITE_VIEW_TYPE.name, this.geocodeTenantNodeFromPostOrTree.bind(this), 'create');
        this.transientEntityService.registerTransientEntityTypeFunction(geocoder_const_1.GEOCODER_PROVIDER, GeocoderService.name, 'Add geocode method definition to get latitude and longitude from address', entity_name_1.EntityName.objectNode, web_site_const_1.WEB_SITE_VIEW_TYPE.name, this.completeWebSiteViewTypeNode.bind(this));
        this.transientEntityService.registerTransientEntityTypeFunction(geocoder_const_1.GEOCODER_PROVIDER, GeocoderService.name, 'Add geocode method definition to get latitude and longitude from address', entity_name_1.EntityName.objectTree, web_site_const_1.WEB_SITE_VIEW_TYPE.name, this.completeWebSiteViewTypeNode.bind(this));
    }
    registerService(geocoderService) {
        this.services.push(geocoderService);
    }
    async completeWebSiteViewTypeNode(objectNode, ctx) {
        var _a;
        if (!objectNode.entityCtx) {
            objectNode.entityCtx = { entityType: entity_name_1.EntityName.objectNode };
        }
        if (!((_a = objectNode.entityCtx) === null || _a === void 0 ? void 0 : _a.actions)) {
            objectNode.entityCtx.actions = {};
        }
        if (!objectNode.entityCtx.actions.methods) {
            objectNode.entityCtx.actions.methods = [];
        }
        objectNode.entityCtx.actions.methods.push({
            methodId: 'geocode',
            methodName: 'Locate an address',
            actionName: 'Locate this address',
            parameters: {
                type: 'object',
                properties: {
                    address: {
                        type: 'string',
                        title: 'Address',
                        required: true,
                    },
                },
            },
            icon: 'fas fa-search-location',
        });
    }
    async geocodeTenantNodeFromPostOrTree(objectNode, args, ctx) {
        const geolocation = await this.getAddressLocation(args.address, ctx);
        return new GeocoderResult(geolocation);
    }
    async getAddressLocation(address, ctx) {
        const result = await this.cachedResultService.getResult(GeocoderService.name, {
            address: address
                .normalize('NFD')
                .replace(/[\u0300-\u036f]/g, '')
                .toLowerCase()
                .replace(new RegExp('[^' + `A-Z|a-z|0-9|` + ']', 'g'), '_')
                .replace(/__+/g, '_'),
        }, async () => {
            for (const geocoderService of this.services) {
                try {
                    return await geocoderService.getAddressLocation(address, false, ctx);
                }
                catch (error) {
                    console.trace(geocoderService.getName(), error);
                }
            }
            throw application_error_1.ApplicationError.unexpectedError(new Error('geocoders not available'));
        }, moment_1.default.duration(2, 'month'));
        return result;
    }
    async geocodeTenantNode(entity, args, ctx) {
        const address = await this.getAddressLocation(decodeURIComponent(args[0].replace(/+/g, ' ')), ctx);
        return new generated_response_1.JsonGeneratedResponse(address);
    }
};
GeocoderService = tslib_1.__decorate([
    tslib_1.__param(0, core_1.service(server_config_service_1.ServerConfigService)),
    tslib_1.__param(1, core_1.service(action_entity_service_1.ActionEntityService)),
    tslib_1.__param(2, core_1.service(cached_result_service_1.CachedResultService)),
    tslib_1.__param(3, core_1.service(transient_entity_service_1.TransientEntityService)),
    tslib_1.__metadata("design:paramtypes", [server_config_service_1.ServerConfigService,
        action_entity_service_1.ActionEntityService,
        cached_result_service_1.CachedResultService,
        transient_entity_service_1.TransientEntityService])
], GeocoderService);
exports.GeocoderService = GeocoderService;
//# sourceMappingURL=geocoder.service.js.map