package org.lantern;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.jivesoftware.smack.packet.Packet;
import org.littleshoot.commom.xmpp.XmppUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Default class for keeping track of which contacts are trusted.
 */
public class DefaultTrustedContactsManager implements TrustedContactsManager {

    private final static Logger log = 
        LoggerFactory.getLogger(DefaultTrustedContactsManager.class);
    
    private static final File CONTACTS_FILE =
        new File(LanternUtils.configDir(), "trusted.txt");
    
    static {
        if (!CONTACTS_FILE.isFile()) {
            try {
                if (!CONTACTS_FILE.createNewFile()) {
                    log.error("Could not create trust file!!");
                } else {
                    CONTACTS_FILE.setWritable(true);
                }
            } catch (final IOException e) {
                log.error("Could not create trust file!!", e);
            }
        }
    }
    
    private final Set<String> trustedContacts;
    
    public DefaultTrustedContactsManager() {
        this.trustedContacts = loadTrustedContacts();
        log.info("Loaded contacts: {}", this.trustedContacts);
    }

    @Override
    public boolean isTrusted(final String email) {
        return trustedContacts.contains(email);
    }
    
    @Override
    public boolean isTrusted(final Packet msg) {
        return isJidTrusted(msg.getFrom());
    }

    private Set<String> loadTrustedContacts() {
        if (!CONTACTS_FILE.isFile()) {
            log.warn("No file to read!!");
            return Collections.emptySet();
        }
        log.info("Reading contacts...file size is: {}", CONTACTS_FILE.length());
        final Set<String> trusted = new HashSet<String>();
        BufferedReader br = null;
        try {
            br = new BufferedReader(new FileReader(CONTACTS_FILE));
            String line = br.readLine();
            while (line != null) {
                log.info("Reading line: {}", line);
                if (StringUtils.isNotBlank(line)) {
                    trusted.add(line.trim());
                }
                line = br.readLine();
            }
            return trusted;
        } catch (final IOException e) {
            log.error("Reading error?", e);
        } finally {
            IOUtils.closeQuietly(br);
        }
        return Collections.emptySet();
    }

    @Override
    public boolean isJidTrusted(final String jid) {
        final String email = XmppUtils.jidToUser(jid);
        return isTrusted(email);
    }

    
    @Override
    public void addTrustedContact(final String email) {
        log.info("Adding trusted contact: {}", email);
        addTrustedContacts(Arrays.asList(email));
    }
    
    @Override
    public void removeTrustedContact(final String email) {
        log.info("Removing trusted contact: {}", email);
        removeTrustedContacts(Arrays.asList(email));
    }
    
    @Override
    public void addTrustedContacts(final Collection<String> trusted) {
        trustedContacts.addAll(trusted);
        writeContacts();
    }

    @Override
    public void removeTrustedContacts(final Collection<String> trusted) {
        trustedContacts.removeAll(trusted);
        writeContacts();
    }

    private void writeContacts() {
        synchronized (CONTACTS_FILE) {
            // We just write the whole thing again from scratch.
            CONTACTS_FILE.delete();
            FileWriter fw = null;
            try {
                fw = new FileWriter(CONTACTS_FILE);
                for (final String email : trustedContacts) {
                    final String newLine = email+"\n";
                    log.info("Adding contact line: {}", newLine);
                    fw.append(newLine);
                }
            } catch (final IOException e) {
                log.error("Could not write to contacts file?");
            } finally {
                IOUtils.closeQuietly(fw);
            }
        }
        log.info("File size after writing: {}", CONTACTS_FILE.length());
    }
}

@@ -137,17 +137,190 @@
 ava.io.I
-O
+nputStream;%0Aimport java.io.InputStreamReader;%0Aimport java.io.IOException;%0Aimport java.io.OutputStream;%0Aimport java.io.OutputStreamWriter;%0Aimport java.security.GeneralSecurity
 Exceptio
@@ -2312,32 +2312,120 @@
 ;%0A        try %7B%0A
+            final InputStream in = LanternUtils.localDecryptInputStream(CONTACTS_FILE);%0A
             br =
@@ -2452,32 +2452,28 @@
 new 
-FileReader(CONTACTS_FILE
+InputStreamReader(in
 ));%0A
@@ -2876,24 +2876,128 @@
 rror?%22, e);%0A
+        %7D catch (final GeneralSecurityException e) %7B%0A            log.error(%22Failed to decrypt: %7B%7D%22, e);%0A
         %7D fi
@@ -4153,20 +4153,28 @@
         
-File
+OutputStream
 Writer f
@@ -4221,41 +4221,148 @@
     
-fw = new FileWriter(CONTACTS_FILE
+OutputStream out =%0A                    LanternUtils.localEncryptOutputStream(CONTACTS_FILE);%0A                fw = new OutputStreamWriter(out
 );%0A 
@@ -4704,24 +4704,150 @@
 ts file?%22);%0A
+            %7D catch (final GeneralSecurityException e) %7B%0A                log.error(%22Failed to encrypt contacts file: %7B%7D%22, e);%0A
             

Encrypt trusted contacts #27