package de.thpeetz.kontor.mailclient.views;

import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.List;
import java.util.Properties;

import javax.mail.Address;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.NoSuchProviderException;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.internet.InternetAddress;

import com.sun.mail.imap.IMAPFolder;
import com.vaadin.flow.component.Composite;
import com.vaadin.flow.component.accordion.Accordion;
import com.vaadin.flow.component.html.Paragraph;
import com.vaadin.flow.component.html.Span;
import com.vaadin.flow.component.menubar.MenuBar;
import com.vaadin.flow.component.messages.MessageList;
import com.vaadin.flow.component.messages.MessageListItem;
import com.vaadin.flow.component.orderedlayout.FlexComponent.Alignment;
import com.vaadin.flow.component.orderedlayout.FlexComponent.JustifyContentMode;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.sidenav.SideNav;
import com.vaadin.flow.component.sidenav.SideNavItem;
import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.router.RouteAlias;
import com.vaadin.flow.server.auth.AnonymousAllowed;
import com.vaadin.flow.theme.lumo.LumoUtility.Gap;

import de.thpeetz.kontor.mailclient.data.MailAccount;
import de.thpeetz.kontor.admin.services.MailService;
import de.thpeetz.kontor.common.views.MainLayout;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@PageTitle("Email")
@AnonymousAllowed
@Route(value = "mail", layout = MainLayout.class)
@RouteAlias(value = "kontor/mail", layout = MainLayout.class)
public class EmailView extends Composite<VerticalLayout> {

    MenuBar menuBar = new MenuBar();
    Accordion accordion = new Accordion();
    SideNav folderList = new SideNav();
    MailService mailService;

    public EmailView(MailService mailService) {
        this.mailService = mailService;
        configureView();
        updateFolderList();
    }

    private void updateFolderList() {
        List<MailAccount> accounts = mailService.findAllMailAccounts();
        MailAccount account = accounts.get(0);

        Properties properties = new Properties();
        properties.put(String.format("mail.%s.host", account.getProtocol()), account.getHost());
        properties.put(String.format("mail.%s.port", account.getProtocol()), account.getPort().toString());
        properties.put("mail.imap.starttls.enable", "true");

        Session session = Session.getDefaultInstance(properties);
        Store store;
        try {
            store = session.getStore(account.getProtocol());
            store.connect(account.getUserName(), account.getPassword());
            Folder rootFolder = store.getDefaultFolder();
            Folder[] folders = rootFolder.list();
            for (Folder value : folders) {
                SideNavItem folder = addSubFolder(value);
                folderList.addItem(folder);
            }
            log.info("{} folders found", folders.length);
            Folder folder = store.getFolder("INBOX");
            IMAPFolder imapFolder = (IMAPFolder) folder;
            imapFolder.open(Folder.READ_ONLY);
            Message[] messages = imapFolder.getMessages();
            log.info("Folder {} opened", folder.getFullName());
            int messageCount = folder.getMessageCount();
            log.info("{} messages found", messages.length);
            for (Message message : messages) {
                log.info("Message {}: {}, {}, {}", message.getMessageNumber(), message.getSubject(), message.getReceivedDate(), message.getSentDate());
                //log.info("Message: {}", message.getAllRecipients());
                Address[] addresses;
                printAddress(message.getRecipients(Message.RecipientType.TO));
                printAddress(message.getRecipients(Message.RecipientType.CC));
                printAddress(message.getRecipients(Message.RecipientType.BCC));
            }
            store.close();
            log.info("Connection closed");
        } catch (NoSuchProviderException e) {
            throw new RuntimeException(e);
        } catch (MessagingException e) {
            throw new RuntimeException(e);
        }
    }

    private void printAddress(Address[] addresses) {
        if (addresses != null) {
            for (Address address: addresses) {
                log.info("Address {}: {}", address.getType(), address.toString());
                InternetAddress internetAddress = (InternetAddress)address;
                log.info("InternetAddress {}: {}", internetAddress.getPersonal(), internetAddress.getAddress());
            }
        }
    }

    private SideNavItem addSubFolder(Folder mailFolder) throws MessagingException {
        log.debug("addSubFolder: {}", mailFolder.getName());
        Span counter = new Span(String.valueOf(mailFolder.getMessageCount()));
        counter.getElement().getThemeList().add("badge contrast pill");
        counter.getElement().setAttribute("aria-label", String.format("%d unread messages", mailFolder.getMessageCount()));
        SideNavItem folder = new SideNavItem(mailFolder.getName());
        folder.setSuffixComponent(counter);
        Folder[] folders = mailFolder.list();
        log.info("{} subfolders found", folders.length);
        for (Folder value : folders) {
            SideNavItem subFolder = addSubFolder(value);
            folder.addItem(subFolder);
        }
        return folder;
    }

    private void configureView() {
        HorizontalLayout layoutMenubar = new HorizontalLayout();
        HorizontalLayout layoutRow2 = new HorizontalLayout();
        VerticalLayout layoutColumn2 = new VerticalLayout();
        VerticalLayout layoutColumn3 = new VerticalLayout();
        MessageList messageList = new MessageList();
        VerticalLayout layoutColumn4 = new VerticalLayout();
        Paragraph textMedium = new Paragraph();
        getContent().setWidth("100%");
        getContent().getStyle().set("flex-grow", "1");
        layoutMenubar.addClassName(Gap.MEDIUM);
        layoutMenubar.setWidth("100%");
        layoutMenubar.setHeight("min-content");
        menuBar.setWidth("min-content");
        setMenuBarSampleData(menuBar);
        layoutRow2.addClassName(Gap.MEDIUM);
        layoutRow2.setWidth("100%");
        layoutRow2.getStyle().set("flex-grow", "1");
        layoutColumn2.getStyle().set("flex-grow", "1");
        accordion.setWidth("100%");
        setAccordionSampleData(accordion);
        layoutColumn3.setHeightFull();
        layoutRow2.setFlexGrow(1.0, layoutColumn3);
        layoutColumn3.setWidth("100%");
        layoutColumn3.getStyle().set("flex-grow", "1");
        layoutColumn3.setJustifyContentMode(JustifyContentMode.START);
        layoutColumn3.setAlignItems(Alignment.START);
        messageList.setWidth("100%");
        setMessageListSampleData(messageList);
        layoutColumn4.setWidthFull();
        layoutColumn3.setFlexGrow(1.0, layoutColumn4);
        layoutColumn4.setWidth("100%");
        layoutColumn4.getStyle().set("flex-grow", "1");
        textMedium.setText(
                "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.");
        textMedium.setWidth("100%");
        textMedium.getStyle().set("font-size", "var(--lumo-font-size-m)");
        getContent().add(layoutMenubar);
        layoutMenubar.add(menuBar);
        getContent().add(layoutRow2);
        layoutRow2.add(layoutColumn2);
        layoutColumn2.add(folderList);
        layoutRow2.add(layoutColumn3);
        layoutColumn3.add(messageList);
        layoutColumn3.add(layoutColumn4);
        layoutColumn4.add(textMedium);
    }

    private void setMenuBarSampleData(MenuBar menuBar) {
        menuBar.addItem("View");
        menuBar.addItem("Edit");
        menuBar.addItem("Share");
        menuBar.addItem("Move");
    }

    private void setAccordionSampleData(Accordion accordion) {
        Span name = new Span("Sophia Williams");
        Span email = new Span("sophia.williams@company.com");
        Span phone = new Span("(501) 555-9128");
        VerticalLayout personalInformationLayout = new VerticalLayout(name, email, phone);
        personalInformationLayout.setSpacing(false);
        personalInformationLayout.setPadding(false);
        accordion.add("Personal information", personalInformationLayout);
        Span street = new Span("4027 Amber Lake Canyon");
        Span zipCode = new Span("72333-5884 Cozy Nook");
        Span city = new Span("Arkansas");
        VerticalLayout billingAddressLayout = new VerticalLayout();
        billingAddressLayout.setSpacing(false);
        billingAddressLayout.setPadding(false);
        billingAddressLayout.add(street, zipCode, city);
        accordion.add("Billing address", billingAddressLayout);
        Span cardBrand = new Span("Mastercard");
        Span cardNumber = new Span("1234 5678 9012 3456");
        Span expiryDate = new Span("Expires 06/21");
        VerticalLayout paymentLayout = new VerticalLayout();
        paymentLayout.setSpacing(false);
        paymentLayout.setPadding(false);
        paymentLayout.add(cardBrand, cardNumber, expiryDate);
        accordion.add("Payment", paymentLayout);
    }

    private void setMessageListSampleData(MessageList messageList) {
        MessageListItem message1 = new MessageListItem("Nature does not hurry, yet everything gets accomplished.",
                LocalDateTime.now().minusDays(1).toInstant(ZoneOffset.UTC), "Matt Mambo");
        message1.setUserColorIndex(1);
        MessageListItem message2 = new MessageListItem(
                "Using your talent, hobby or profession in a way that makes you contribute with something good to this world is truly the way to go.",
                LocalDateTime.now().minusMinutes(55).toInstant(ZoneOffset.UTC), "Linsey Listy");
        message2.setUserColorIndex(2);
        messageList.setItems(message1, message2);
    }
}
