/*-
 * ~~~~~~licensing~~~~~~
 * entaxy-audit
 * ==========
 * Copyright (C) 2020 - 2025 EmDev LLC
 * ==========
 * You may not use this file except in accordance with the License Terms of the Copyright
 * Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
 * rights to the Software and any copies are the property of the Copyright Holder. Unless
 * it is explicitly allowed the Copyright Holder, the User is prohibited from using the
 * Software for commercial purposes to provide services to third parties.
 * 
 * The Copyright Holder hereby declares that the Software is provided on an "AS IS".
 * Under no circumstances does the Copyright Holder guarantee or promise that the
 * Software provided by him will be suitable or not suitable for the specific purposes
 * of the User, that the Software will meet all commercial and personal subjective
 * expectations of the User, that the Software will work properly, without technical
 * errors, quickly and uninterruptedly.
 * 
 * Under no circumstances shall the Copyright Holder or its Affiliates is not liable
 * to the User for any direct or indirect losses of the User, his expenses or actual
 * damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
 * or damage to data, property, etc.
 * ~~~~~~/licensing~~~~~~
 */
package ru.entaxy.audit.service.impl;

import javax.security.auth.Subject;
import javax.servlet.http.HttpServletRequest;

import org.osgi.service.event.Event;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import ru.entaxy.audit.data.AuditEvent;
import ru.entaxy.audit.data.Outcome;
import ru.entaxy.audit.service.AuditService;
import ru.entaxy.audit.service.InterpretedEvent;
import ru.entaxy.audit.utils.AuditHelper;

public class AuditServiceImpl implements AuditService {

    private static final Logger LOG = LoggerFactory.getLogger(AuditServiceImpl.class);

    private final WebLoginModule webLoginModule = new WebLoginModule();
    private final OSGIEventModule osgiEventModule = new OSGIEventModule();

    @Override
    public void onAudit(AuditEvent record) {
        throw new RuntimeException("Not implemented");
    }

    @Override
    public void onLogin(String username, HttpServletRequest request, Outcome outcome) {
        webLoginModule.onLogin(username, request, outcome);
    }

    @Override
    public void onLogout(String username, HttpServletRequest request) {
        webLoginModule.onLogout(username, request);
    }

    @Override
    public void onOSGIEvent(Event event) {
        osgiEventModule.onEvent(event);
    }

    @Override
    public void onFileChange(Event event) {
        osgiEventModule.onFileChange(event);
    }

    @Override
    public boolean interpret(Event event) {
        if (InterpreterService.INSTANCE == null)
            return false;
        InterpretedEvent result = InterpreterService.INSTANCE.interpret(event);

        if (result == null) {
            if (LOG.isTraceEnabled())
                LOG.trace("Event from topic [{}] not interpreted", event.getTopic());
            return false;
        }

        if (result.resolution.equals(InterpretedEvent.EventResolution.IGNORE)) {
            if (LOG.isTraceEnabled())
                LOG.trace("Event from topic [{}] IGNORED; interpreted as [{}] -> [{}]", event.getTopic(),
                        result.getClass().getName());
            return false;
        }


        if (ConverterService.INSTANCE == null)
            return false;

        AuditEvent convertedEvent = ConverterService.INSTANCE.convert(result);

        if (convertedEvent == null) {
            if (LOG.isDebugEnabled())
                LOG.debug("NOT CONVERTED: Event from topic [{}] interpreted as [{}]", event.getTopic(),
                        result.getClass().getName());
            return false;
        }

        Subject subject = (Subject) event.getProperty("subject");
        boolean processed = false;

        String suser = "local";
        String address = "localhost";

        if (subject != null) {
            suser = AuditHelper.findRemoteUser(subject);
            address = AuditHelper.findAddress(subject);
        }

        AuditEvent auditEvent = AuditEvent.AuditLoggingEventBuilder.getInstance()
                .category(convertedEvent.getCategory())
                .duser(convertedEvent.getDuser())
                .message(convertedEvent.getMessage())
                .outcome(convertedEvent.getOutcome())
                .severity(convertedEvent.getSeverity())
                .src(convertedEvent.getSrc() != null ? convertedEvent.getSrc() : address)
                .suser(convertedEvent.getSuser() != null ? convertedEvent.getSuser() : suser)
                .target(convertedEvent.getTarget())
                .build();


        AuditHelper.log(auditEvent);
        processed = true;

        return processed;
    }

    @Override
    public void setRequestAndSubject(Subject subject, HttpServletRequest request) {
        webLoginModule.setMDC(subject, request);
    }

    @Override
    public void setRequestAndUser(String user, HttpServletRequest request) {
        webLoginModule.setMDC(user, request);
    }
}
