package fr.jcgay.notification.notifier.systemtray;

import com.google.common.base.MoreObjects;
import com.google.common.base.Objects;
import fr.jcgay.notification.Application;
import fr.jcgay.notification.DiscoverableNotifier;
import fr.jcgay.notification.Notification;
import fr.jcgay.notification.Notifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.awt.*;
import java.awt.TrayIcon.MessageType;

import static java.util.concurrent.TimeUnit.SECONDS;

public class SystemTrayNotifier implements DiscoverableNotifier {

    private static final Logger LOGGER = LoggerFactory.getLogger(SystemTrayNotifier.class);

    private final Application application;

    private boolean skipNotifications;
    private TrayIcon icon;

    public SystemTrayNotifier(Application application) {
        LOGGER.debug("Configuring System Tray for application {}.", application);
        this.application = application;
    }

    @Override
    public Notifier init() {
        if (icon != null) {
            return this;
        }

        if (!SystemTray.isSupported()) {
            skipNotifications = true;
            LOGGER.warn("SystemTray is not supported, skipping notifications...");
            return this;
        }

        icon = new TrayIcon(createImage(application.icon().toByteArray()), application.name());
        icon.setImageAutoSize(true);

        try {
            SystemTray.getSystemTray().add(icon);
        } catch (AWTException e) {
            throw new SystemTrayNotificationException("Error initializing SystemTray Icon.", e);
        }

        return this;
    }

    @Override
    public void send(Notification notification) {
        if (!skipNotifications) {
            icon.setImage(createImage(notification.icon().toByteArray()));
            icon.displayMessage(notification.title(), notification.message(), toMessageType(notification.level()));
        }
    }

    @Override
    public void close() {
        if (!skipNotifications) {
            try {
                Thread.sleep(application.timeout() == -1 ? SECONDS.toMillis(2) : application.timeout());
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
            SystemTray.getSystemTray().remove(icon);
        }
    }

    @Override
    public boolean isPersistent() {
        return true;
    }

    @Override
    public boolean tryInit() {
        init();
        return !skipNotifications;
    }

    private static MessageType toMessageType(Notification.Level level) {
        switch (level) {
            case INFO:
                return MessageType.INFO;
            case WARNING:
                return MessageType.WARNING;
            case ERROR:
                return MessageType.ERROR;
            default:
                return MessageType.NONE;
        }
    }

    private Image createImage(byte[] imageData) {
        return Toolkit.getDefaultToolkit().createImage(imageData);
    }

    @Override
    public int hashCode() {
        return Objects.hashCode(application);
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null || getClass() != obj.getClass()) {
            return false;
        }
        final SystemTrayNotifier other = (SystemTrayNotifier) obj;
        return Objects.equal(this.application, other.application);
    }

    @Override
    public String toString() {
        return MoreObjects.toStringHelper(this)
            .add("application", application)
            .toString();
    }
}