package com.lucifer.rnmail;

import android.support.annotation.Nullable;

import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.ReadableNativeArray;
import com.facebook.react.bridge.WritableArray;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.bridge.WritableNativeArray;
import com.facebook.react.bridge.WritableNativeMap;
import com.facebook.react.modules.core.DeviceEventManagerModule;
import com.sun.mail.imap.IMAPFolder;
import com.sun.mail.imap.IMAPStore;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.Map;
import java.util.Properties;

import javax.mail.AuthenticationFailedException;
import javax.mail.Authenticator;
import javax.mail.Flags;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Part;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;


public class RNLuciferImapModuleCopy extends ReactContextBaseJavaModule {

    private final ReactApplicationContext reactContext;

    public RNLuciferImapModuleCopy(ReactApplicationContext reactContext) {
        super(reactContext);
        this.reactContext = reactContext;
    }

    private void sendEvent(ReactContext reactContext,
                           String eventName,
                           @Nullable WritableMap params) {
        reactContext
                .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
                .emit(eventName, params);
    }

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

    @Override
    public String getName() {
        return "RNLuciferMail";
    }

    @ReactMethod
    void connectImapServer(ReadableMap args, final Callback callback) {
        final String _imapserver = args.getString("imapserver");
        final String _usermail = args.getString("usermail");
        final String _password = args.getString("password");
        final String _port = args.getString("port");

        new Thread(new Runnable() {
            @Override
            public void run() {
                final String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory";
                Properties prop = System.getProperties();
                prop.put("mail.imap.host", _imapserver);
                prop.put("mail.imap.port", _port);
                prop.setProperty("mail.imap.ssl.enable", "true");
                prop.setProperty("mail.smtp.socketFactory.class", SSL_FACTORY);
                prop.put("mail.imap.auth.plain.disable", "true");
                Session mailsession = Session.getInstance(prop, null);
                mailsession.setDebug(false); //是否启用debug模式
                IMAPStore store = null;
                try {
                    store = (IMAPStore) mailsession.getStore("imaps");  // 使用imap会话机制，连接服务器
                    store.connect(_imapserver, _usermail, _password);
                    callback.invoke(200);       //授权成功
                } catch (AuthenticationFailedException e) {
                    e.printStackTrace();
                    callback.invoke(1);       // 授权失败
                } catch (MessagingException e) {
                    e.printStackTrace();
                    callback.invoke(2);         //其他错误
                } catch (Exception e) {
                    e.printStackTrace();
                    callback.invoke(3);         //未知错误
                } finally {
                    try {
                        if (store != null)
                            store.close();
                    } catch (Exception bs) {
                        bs.printStackTrace();
                    }
                }
            }
        }).start();
    }

    /*
     * 获取邮件Uids
     * * */
    @ReactMethod
    public void getMailUidsAsync(ReadableMap args, final Callback callback) {
        final String _server = args.getString("imapserver");
        final String _usermail = args.getString("usermail");
        final String _password = args.getString("password");
        final String _port = args.getString("port");
        final String _folderName = args.hasKey("folderName") ? args.getString("folderName") : "";

        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    String imapserver = _server; // 邮件服务器
                    String user = _usermail;
                    String pwd = _password;

                    final String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory";// 获取默认会话
                    Properties prop = System.getProperties();
                    prop.put("mail.imap.host", imapserver);
                    prop.put("mail.imap.port", _port);
                    prop.setProperty("mail.imap.ssl.enable", "true");
                    prop.setProperty("mail.smtp.socketFactory.class", SSL_FACTORY);
                    prop.put("mail.imap.auth.plain.disable", "true");
                    Session mailsession = Session.getInstance(prop, null);
                    mailsession.setDebug(false); //是否启用debug模式
                    IMAPStore store = null;
                    IMAPFolder folderS = null;
                    IMAPFolder folder = null;
                    try {
                        store = (IMAPStore) mailsession.getStore("imaps");  // 使用imap会话机制，连接服务器
                        store.connect(imapserver, user, pwd);

                        folder = (IMAPFolder) store.getFolder("Inbox"); //收件箱
                        folder.open(Folder.READ_ONLY);
                        Message[] messages = folder.getMessages();

                        if (messages.length > 0) {
                            WritableArray inUidsArray = new WritableNativeArray();
                            for (int i = 0; i < messages.length; i++) {
                                try {
                                    inUidsArray.pushInt((int) folder.getUID((MimeMessage) messages[i]));
                                    if (i % 10 == 0 && i > 0) {
                                        WritableMap mailMap = new WritableNativeMap();
                                        mailMap.putString("account", _usermail);
                                        mailMap.putArray("uids", inUidsArray);
                                        mailMap.putString("folder", "Inbox");
                                        sendEvent(reactContext, "ASYNC_GET_MAIL_UIDS", mailMap);
                                        inUidsArray = new WritableNativeArray();
                                    }
                                    if (i == messages.length - 1 && inUidsArray.size() > 0) {
                                        WritableMap mailMap = new WritableNativeMap();
                                        mailMap.putString("account", _usermail);
                                        mailMap.putArray("uids", inUidsArray);
                                        mailMap.putString("folder", "Inbox");
                                        sendEvent(reactContext, "ASYNC_GET_MAIL_UIDS", mailMap);
                                    }
                                } catch (Exception e) {
                                    // TODO Auto-generated catch block
                                    e.printStackTrace();
                                }
                            }
                        }


                        folderS = (IMAPFolder) store.getFolder("Sent"); //收件箱
                        folderS.open(Folder.READ_ONLY);
                        messages = folderS.getMessages();

                        if (messages.length > 0) {
                            WritableArray sentUidsArray = new WritableNativeArray();
                            for (int i = 0; i < messages.length; i++) {
                                try {
                                    sentUidsArray.pushInt((int) folderS.getUID((MimeMessage) messages[i]));
                                    if (i % 10 == 0 && i > 0) {
                                        WritableMap mailMap = new WritableNativeMap();
                                        mailMap.putString("account", _usermail);
                                        mailMap.putArray("uids", sentUidsArray);
                                        mailMap.putString("folder", "Sent");
                                        sendEvent(reactContext, "ASYNC_GET_MAIL_UIDS", mailMap);
                                        sentUidsArray = new WritableNativeArray();
                                    }
                                    if (i == messages.length - 1 && sentUidsArray.size() > 0) {
                                        WritableMap mailMap = new WritableNativeMap();
                                        mailMap.putString("account", _usermail);
                                        mailMap.putArray("uids", sentUidsArray);
                                        mailMap.putString("folder", "Sent");
                                        sendEvent(reactContext, "ASYNC_GET_MAIL_UIDS", mailMap);
                                    }
                                } catch (Exception e) {
                                    // TODO Auto-generated catch block
                                    e.printStackTrace();
                                }
                            }
                        }
                        callback.invoke(true);
                    } catch (MessagingException ex) {
                        ex.printStackTrace();
                        callback.invoke(false);
                    } finally {
                        try {
                            if (folder != null)
                                folder.close(true); //退出收件箱时,删除做了删除标识的邮件
                            if (folderS != null)
                                folderS.close(true); //退出收件箱时,删除做了删除标识的邮件
                            if (store != null)
                                store.close();
                        } catch (Exception bs) {
                            bs.printStackTrace();
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    callback.invoke(false);
                }
            }
        }).start();
    }

    /*
     * 获取邮件Uids
     * * */
    @ReactMethod
    public void getMailUids(ReadableMap args, final Callback callback) {
        final String _server = args.getString("imapserver");
        final String _usermail = args.getString("usermail");
        final String _password = args.getString("password");
        final String _port = args.getString("port");
        final String _folderName = args.hasKey("folderName") ? args.getString("folderName") : "";

        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    String imapserver = _server; // 邮件服务器
                    String user = _usermail;
                    String pwd = _password;
                    String folderName = _folderName;

                    final String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory";// 获取默认会话
                    Properties prop = System.getProperties();
                    prop.put("mail.imap.host", imapserver);
                    prop.put("mail.imap.port", _port);
                    prop.setProperty("mail.imap.ssl.enable", "true");
                    prop.setProperty("mail.smtp.socketFactory.class", SSL_FACTORY);
                    prop.put("mail.imap.auth.plain.disable", "true");
                    Session mailsession = Session.getInstance(prop, null);
                    mailsession.setDebug(false); //是否启用debug模式
                    IMAPStore store = null;
                    IMAPFolder folderS = null;
                    IMAPFolder folder = null;
                    try {
                        store = (IMAPStore) mailsession.getStore("imaps");  // 使用imap会话机制，连接服务器
                        store.connect(imapserver, user, pwd);

                        WritableMap mailMap = new WritableNativeMap();
                        mailMap.putString("account", _usermail);
                        if (_folderName.isEmpty()) {
                            folder = (IMAPFolder) store.getFolder("Inbox"); //收件箱
                            folder.open(Folder.READ_ONLY);
                            Message[] messages = folder.getMessages();

                            WritableArray inUidsArray = new WritableNativeArray();
                            if (messages.length > 0) {
                                //倒叙
                                for (int i = messages.length - 1; i >= 0; i--) {
                                    try {
                                        inUidsArray.pushInt((int) folder.getUID((MimeMessage) messages[i]));
                                    } catch (Exception e) {
                                        // TODO Auto-generated catch block
                                        e.printStackTrace();
                                    }
                                }
                            }
                            mailMap.putArray("Inbox", inUidsArray);

                            folderS = (IMAPFolder) store.getFolder("Sent"); //收件箱
                            folderS.open(Folder.READ_ONLY);
                            messages = folderS.getMessages();
                            WritableArray sentUidsArray = new WritableNativeArray();
                            if (messages.length > 0) {
                                //倒叙
                                for (int i = messages.length - 1; i >= 0; i--) {
                                    try {
                                        sentUidsArray.pushInt((int) folderS.getUID((MimeMessage) messages[i]));
                                    } catch (Exception e) {
                                        // TODO Auto-generated catch block
                                        e.printStackTrace();
                                    }
                                }
                            }
                            mailMap.putArray("Sent", sentUidsArray);
                        } else {
                            folder = (IMAPFolder) store.getFolder(_folderName); //收件箱
                            folder.open(Folder.READ_ONLY);
                            Message[] messages = folder.getMessages();
                            WritableArray inUidsArray = new WritableNativeArray();
                            if (messages.length > 0) {
                                //倒叙
                                for (int i = messages.length - 1; i >= 0; i--) {
                                    try {
                                        inUidsArray.pushInt((int) folder.getUID((MimeMessage) messages[i]));
                                    } catch (Exception e) {
                                        // TODO Auto-generated catch block
                                        e.printStackTrace();
                                    }
                                }
                            }
                            mailMap.putArray(_folderName, inUidsArray);
                        }
                        callback.invoke(mailMap);
                    } catch (MessagingException ex) {
                        ex.printStackTrace();
                        callback.invoke(false);
                    } finally {
                        try {
                            if (folder != null)
                                folder.close(true); //退出收件箱时,删除做了删除标识的邮件
                            if (folderS != null)
                                folderS.close(true); //退出收件箱时,删除做了删除标识的邮件
                            if (store != null)
                                store.close();
                        } catch (Exception bs) {
                            bs.printStackTrace();
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    callback.invoke(false);
                }
            }
        }).start();
    }

    /**
     * 根据Uid 获取邮件详情
     */

    @ReactMethod
    public void getMailWithUids(ReadableMap args, final Callback callback) {
        final String _server = args.getString("imapserver");
        final String _usermail = args.getString("usermail");
        final String _password = args.getString("password");
        final ReadableMap _uids = args.getMap("uids");
        final String _port = args.getString("port");
        final String _folderName = args.hasKey("folderName") ? args.getString("folderName") : "";

        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    String imapserver = _server; // 邮件服务器
                    String user = _usermail;
                    String pwd = _password;
                    String folderName = _folderName;

                    final String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory";// 获取默认会话
                    Properties prop = System.getProperties();
                    prop.put("mail.imap.host", imapserver);
                    prop.put("mail.imap.port", _port);
                    prop.setProperty("mail.imap.ssl.enable", "true");
                    prop.setProperty("mail.smtp.socketFactory.class", SSL_FACTORY);
                    prop.put("mail.imap.auth.plain.disable", "true");
                    Session mailsession = Session.getInstance(prop, null);
                    mailsession.setDebug(false); //是否启用debug模式

                    ReadableArray inboxUids = _uids.hasKey("Inbox") ? _uids.getArray("Inbox") : new WritableNativeArray();
                    ReadableArray sentUids = _uids.hasKey("Sent") ? _uids.getArray("Sent") : new WritableNativeArray();

                    IMAPStore store = null;
                    IMAPFolder folder = null;
                    IMAPFolder sfolder = null;

                    try {
                        store = (IMAPStore) mailsession.getStore("imaps");  // 使用imap会话机制，连接服务器
                        store.connect(imapserver, user, pwd);


                        if (inboxUids.size() > 0) {
                            folder = (IMAPFolder) store.getFolder("Inbox"); //收件箱
                            folder.open(Folder.READ_WRITE);

                            int i = 0;
                            while (i < inboxUids.size()) {
                                if (i + 5 <= inboxUids.size()) {
                                    long[] uids = new long[5];
                                    uids[0] = (long) inboxUids.getInt(i);
                                    uids[1] = (long) inboxUids.getInt(i + 1);
                                    uids[2] = (long) inboxUids.getInt(i + 2);
                                    uids[3] = (long) inboxUids.getInt(i + 3);
                                    uids[4] = (long) inboxUids.getInt(i + 4);
                                    getMailDetail(uids, _usermail, "Inbox", folder);
                                    i += 5;
                                } else {
                                    long[] uids = new long[inboxUids.size() - i];
                                    for (int t = 0; t < inboxUids.size() - i; t++) {
                                        uids[t] = (long) inboxUids.getInt(i + t);
                                    }
                                    i = inboxUids.size();
                                    getMailDetail(uids, _usermail, "Inbox", folder);
                                }
                            }
                        }

                        if (sentUids.size() > 0) {
                            sfolder = (IMAPFolder) store.getFolder("Sent"); //收件箱
                            sfolder.open(Folder.READ_WRITE);

                            int i = 0;
                            while (i < sentUids.size()) {
                                if (i + 5 <= sentUids.size()) {
                                    long[] uids = new long[5];
                                    uids[0] = (long) sentUids.getInt(i);
                                    uids[1] = (long) sentUids.getInt(i + 1);
                                    uids[2] = (long) sentUids.getInt(i + 2);
                                    uids[3] = (long) sentUids.getInt(i + 3);
                                    uids[4] = (long) sentUids.getInt(i + 4);
                                    getMailDetail(uids, _usermail, "Sent", sfolder);
                                    i += 5;
                                } else {
                                    long[] uids = new long[sentUids.size() - i];
                                    for (int t = 0; t < sentUids.size() - i; t++) {
                                        uids[t] = (long) sentUids.getInt(i + t);
                                    }
                                    i = sentUids.size();
                                    getMailDetail(uids, _usermail, "Sent", sfolder);
                                }
                            }
                        }
                        callback.invoke(true);
                    } catch (MessagingException ex) {
                        callback.invoke(false);
                        ex.printStackTrace();
                    } finally {
                        // 释放资源
                        try {
                            if (folder != null)
                                folder.close(true); //退出收件箱时,删除做了删除标识的邮件
                            if (sfolder != null)
                                sfolder.close(true); //退出收件箱时,删除做了删除标识的邮件
                            if (store != null)
                                store.close();
                        } catch (Exception bs) {
                            bs.printStackTrace();
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    callback.invoke(false);
                }
            }

            private void getMailDetail(long[] uids, String username, String folderName, final IMAPFolder folder) {
                try {
                    System.out.println(Arrays.toString(uids));

                    Message[] messages = folder.getMessagesByUID(uids);
                    WritableArray mailsArray = new WritableNativeArray();
                    WritableArray uidsarr = new WritableNativeArray();
                    if (messages.length > 0) {
                        ReciveOneMail pmm = null;
                        for (int i = messages.length - 1; i >= 0; i--) {
                            pmm = new ReciveOneMail((MimeMessage) messages[i]);
                            try {
                                boolean isRead;// 用来判断该邮件是否为已读
                                Flags flags = messages[i].getFlags();
                                if (flags.contains(Flags.Flag.SEEN)) {
                                    isRead = true;
                                } else {
                                    isRead = false;
                                }
                                messages[i].setFlag(Flags.Flag.SEEN, true);

                                pmm.getMailContent((Part) messages[i]);
                                WritableMap mailMap = new WritableNativeMap();
                                mailMap.putBoolean("hasRead", isRead);
                                WritableArray attacharray = pmm.getAttachArray();
                                if (attacharray.size() > 0) {
                                    mailMap.putBoolean("hasAttach", true);
                                } else {
                                    mailMap.putBoolean("hasAttach", false);
                                }

                                int uid = (int) folder.getUID((MimeMessage) messages[i]);
                                uidsarr.pushInt(uid);
                                mailMap.putArray("attachs", attacharray);
                                mailMap.putString("from", pmm.getFrom());
                                mailMap.putString("mailAccount", _usermail);                //标记邮箱从属，判断邮件来自哪个邮箱
                                mailMap.putInt("uid", uid);
                                mailMap.putString("to", pmm.getMailAddress("to"));
                                mailMap.putString("cc", pmm.getMailAddress("cc"));
                                mailMap.putString("bcc", pmm.getMailAddress("bcc"));
                                mailMap.putString("fromaddress", pmm.getFromAddress());
                                mailMap.putString("toaddr", pmm.getOnlyMailAddress("to"));
                                mailMap.putString("ccaddr", pmm.getOnlyMailAddress("cc"));
                                mailMap.putString("bccaddr", pmm.getOnlyMailAddress("bcc"));
                                mailMap.putString("subject", pmm.getSubject());
                                mailMap.putString("time", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(messages[i].getSentDate()));
//                            mailMap.putInt("totalcount", total);
                                mailMap.putInt("messageNumber", messages[i].getMessageNumber());
                                mailMap.putArray("content", pmm.getBodyArray());
                                mailsArray.pushMap(mailMap);
                            } catch (Exception e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }
                        }
                        WritableMap mailsMap = new WritableNativeMap();
                        mailsMap.putArray("mails", mailsArray);
                        mailsMap.putArray("uids", uidsarr);
                        mailsMap.putString("account", username);
                        mailsMap.putString("folder", folderName);
                        sendEvent(reactContext, "GET_MAIL_WITH_UIDS", mailsMap);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

    @ReactMethod
    public void SendMail(ReadableMap args, final Callback callback) {
        final String _brand = args.getString("imapserver");
        final String _usermail = args.getString("usermail");
        final String _password = args.getString("password");
        final String _port = args.hasKey("port") ? args.getString("port") : "587";
        final String _subject = args.hasKey("subject") ? args.getString("subject") : "";
        final String _content = args.hasKey("content") ? args.getString("content") : "";
        final String _toAddr = args.hasKey("toaddr") ? args.getString("toaddr") : "";
        final String _ccAddr = args.hasKey("ccaddr") ? args.getString("ccaddr") : "";

        new Thread(new Runnable() {
            @Override
            public void run() {

                try {

                    Properties props = System.getProperties();
                    props.setProperty("mail.smtp.host", _brand);
                    props.setProperty("mail.smtp.port", _port);
                    props.put("mail.smtp.auth", "true");
                    props.put("mail.smtp.starttls.enable", "true");

                    final String username = _usermail;
                    final String password = _password;

                    Session session = Session.getInstance(props, new Authenticator() {
                        protected PasswordAuthentication getPasswordAuthentication() {
                            return new PasswordAuthentication(username, password);
                        }
                    });
                    session.setDebug(true);
                    Date sentdate = new Date();
                    // -- Create a new message --
                    Message msg = new MimeMessage(session);
                    // -- Set the FROM and TO fields --
                    msg.setFrom(new InternetAddress(username));
                    msg.setRecipients(Message.RecipientType.TO,
                            InternetAddress.parse(_toAddr, false));
                    msg.setRecipients(Message.RecipientType.CC,
                            InternetAddress.parse(_ccAddr, false));
                    msg.setSubject(_subject);
                    msg.setText(_content);
                    msg.setSentDate(sentdate);
                    Transport.send(msg);

                    callback.invoke(true);
                } catch (Exception e) {
                    callback.invoke(false);
                    e.printStackTrace();
                }
            }
        }).start();
    }

}
