package cz.muni.fi.pa165.core.smartmeter;

import cz.muni.fi.pa165.core.common.DomainFacade;
import cz.muni.fi.pa165.core.device.DeviceService;
import cz.muni.fi.pa165.core.helpers.exceptions.EntityDeletionException;
import cz.muni.fi.pa165.core.house.HouseService;
import cz.muni.fi.pa165.core.metrics.MetricsFacade;
import cz.muni.fi.pa165.core.metrics.MetricsService;
import cz.muni.fi.pa165.model.dto.smartDevice.SmartMeterCreateDto;
import cz.muni.fi.pa165.model.dto.smartDevice.SmartMeterDto;
import cz.muni.fi.pa165.model.dto.smartDevice.SmartMeterUpdateDto;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

@Component
public class SmartMeterFacade extends DomainFacade<SmartMeter,
		SmartMeterDto,
		SmartMeterCreateDto,
		SmartMeterUpdateDto> {
	private final SmartMeterService smartMeterService; // For the "SmartMeterService" specific methods
	private final DeviceService deviceService;
	private final HouseService houseService;
	private final MetricsService metricsService;

	private final MetricsFacade metricsFacade;

	@Autowired
	public SmartMeterFacade(SmartMeterService smartMeterService,
							SmartMeterMapper smartMeterMapper,
							DeviceService deviceService, HouseService houseService, MetricsService metricsService, MetricsFacade metricsFacade) {
		super(smartMeterService, smartMeterMapper);
		this.smartMeterService = smartMeterService;
		this.deviceService = deviceService;
		this.houseService = houseService;
		this.metricsService = metricsService;
		this.metricsFacade = metricsFacade;
	}

	@Override
	public SmartMeterDto create(SmartMeterCreateDto smartMeterCreateDto) {
		SmartMeter smartMeter = mapper.fromCreateDto(smartMeterCreateDto);
		smartMeter.setActive(false);
		smartMeter.setDevice(deviceService.findById(smartMeterCreateDto.getDeviceId()));
		smartMeter.setHouse(houseService.findById(smartMeterCreateDto.getHouseId()));
		return mapper.toDto(smartMeterService.create(smartMeter));
	}

	@Override
	@Transactional
	public SmartMeterDto deleteById(String id) throws EntityDeletionException {
		// soft delete Smart Devices
		SmartMeter smartMeter = smartMeterService.findById(id);
		metricsService.deleteAllById(smartMeter.getMetricsList().stream().map(sm -> smartMeter.getId()).toArray(String[]::new));

		SmartMeter smartMeterDeleted = smartMeterService.deleteById(smartMeter.getId());
		return mapper.toDto(smartMeterDeleted);
	}

	@Transactional
	public SmartMeterDto changeActiveState(String id, boolean newState){
		SmartMeter smartMeter = smartMeterService.findById(id);
		smartMeter.setActive(newState);
		smartMeterService.update(smartMeter, id);
		return mapper.toDto(smartMeter);
	}

	public void deleteSmartMetersWithItsEntities(SmartMeter smartMeter) throws EntityDeletionException {
		smartMeter.getMetricsList().forEach(metric -> {
			try {
				this.metricsFacade.deleteMetricsById(metric.getId());
			} catch (EntityDeletionException e) {
				throw new RuntimeException(e);
			}
		});
		this.smartMeterService.deleteById(smartMeter.getId());
	}
}
