package com.Pau.ImapNotes2;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.ListIterator;

import org.apache.commons.io.FileUtils;

import com.Pau.ImapNotes2.R;
import com.Pau.ImapNotes2.Data.NotesDb;
import com.Pau.ImapNotes2.Miscs.Imaper;
import com.Pau.ImapNotes2.Miscs.OneNote;
import com.Pau.ImapNotes2.Data.ImapNotes2Account;
import com.Pau.ImapNotes2.Miscs.UpdateThread;
import com.Pau.ImapNotes2.Miscs.SyncThread;
import com.Pau.ImapNotes2.Sync.SyncService;
import com.Pau.ImapNotes2.Sync.SyncUtils;

import android.accounts.Account;
import android.accounts.AccountManager;
import android.accounts.OnAccountsUpdateListener;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.app.SearchManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.PeriodicSync;
import android.content.pm.PackageInfo;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.ListView;
import android.widget.SearchView;
import android.widget.SimpleAdapter;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

public class Listactivity extends Activity  implements OnItemSelectedListener,Filterable {
    private static final int SEE_DETAIL = 2;
    private static final int DELETE_BUTTON = 3;
    private static final int NEW_BUTTON = 4;
    private static final int SAVE_BUTTON = 5;
    private static final int EDIT_BUTTON = 6;
        
    private ArrayList<OneNote> noteList;
    private NotesListAdapter listToView;
    private ArrayAdapter<String> spinnerList;
    
    private Imaper imapFolder;
    private static NotesDb storedNotes = null;
    private Spinner accountSpinner;
    public static ImapNotes2Account imapNotes2Account;
    private static AccountManager accountManager;
    private static Account[] accounts;
    private static List<String> currentList;
    private TextView status = null;
    private static String OldStatus;
    private Button editAccountButton=null;
    private ListView listview;
    public static final String AUTHORITY = "com.Pau.ImapNotes2.provider";
    private static final String TAG = "IN_Listactivity";
    

    private OnClickListener clickListenerEditAccount = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // Clic on editAccount Button
            Intent res = new Intent();
            String mPackage = "com.Pau.ImapNotes2";
            String mClass = ".AccontConfigurationActivity";
            res.setComponent(new ComponentName(mPackage,mPackage+mClass));
            res.putExtra("action", "EDIT_ACCOUNT");
            res.putExtra("accountname", Listactivity.imapNotes2Account.GetAccountname());
            startActivity(res);
        }
    };
    
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    
    // Accounts spinner
    this.accountSpinner = (Spinner) findViewById(R.id.accountSpinner);
    Listactivity.currentList = new ArrayList<String>();
    // Spinner item selection Listener
    this.accountSpinner.setOnItemSelectedListener(this);

    imapNotes2Account = new ImapNotes2Account();
    Listactivity.accountManager = AccountManager.get(getApplicationContext());
    Listactivity.accountManager.addOnAccountsUpdatedListener((OnAccountsUpdateListener)
        new AccountsUpdateListener(), null, true);

    status = (TextView)findViewById(R.id.status);

    this.spinnerList = new ArrayAdapter<String>
        (this, android.R.layout.simple_spinner_item,Listactivity.currentList);
    spinnerList.setDropDownViewResource
        (android.R.layout.simple_spinner_dropdown_item);
    this.accountSpinner.setAdapter(spinnerList);

    this.noteList = new ArrayList<OneNote>();
    ((ImapNotes2)this.getApplicationContext()).SetNotesList(this.noteList);
    this.listToView = new NotesListAdapter(
        getApplicationContext(),
        this.noteList,
        R.layout.note_element,
        new String[]{"title","date"},
        new int[]{R.id.noteTitle, R.id.noteInformation});
    listview = (ListView) findViewById(R.id.notesList);
    listview.setAdapter(this.listToView);

    listview.setTextFilterEnabled(true);
    
    this.imapFolder = new Imaper();
    ((ImapNotes2)this.getApplicationContext()).SetImaper(this.imapFolder);
    
    if (Listactivity.storedNotes == null)
        storedNotes = new NotesDb(getApplicationContext());
    
    // When item is clicked, we go to NoteDetailActivity
    listview.setOnItemClickListener(new OnItemClickListener() {
        public void onItemClick(AdapterView<?> arg0, View widget, int selectedNote, long arg3) {
            Intent toDetail = new Intent(widget.getContext(), NoteDetailActivity.class);
            toDetail.putExtra("selectedNote", (OneNote)arg0.getItemAtPosition(selectedNote));
            toDetail.putExtra("useSticky", Listactivity.imapNotes2Account.GetUsesticky());
            startActivityForResult(toDetail,SEE_DETAIL); 
        }
      });

      editAccountButton = (Button) findViewById(R.id.editAccountButton);
      editAccountButton.setOnClickListener(clickListenerEditAccount);

    }

    public void onDestroy() {
        super.onDestroy();
        // in case of debug, uncomment next instruction
        // logcat will be sent by mail
        // send mail action is done by the user, so he can refuse
        // SendLogcatMail();
//        this.imapFolder.SetPrefs();
    }

    public void onStart() {
        super.onStart();
        int len = this.accounts == null ? 0 : this.accounts.length;
        if (len > 0) updateAccountSpinner();
    }
    
    @Override
    protected void onResume() {
        super.onResume();
        registerReceiver(syncFinishedReceiver, new IntentFilter(SyncService.SYNC_FINISHED));
    }

    @Override
    protected void onPause() {
        super.onPause();
        unregisterReceiver(syncFinishedReceiver);
    }

    private BroadcastReceiver syncFinishedReceiver = new BroadcastReceiver() {

        public void onReceive(Context context, Intent intent) {
            String accountname = intent.getStringExtra("ACCOUNTNAME");
            Boolean isChanged = intent.getBooleanExtra("CHANGED", false);
            Boolean isSynced = intent.getBooleanExtra("SYNCED", false);
            String syncInterval = intent.getStringExtra("SYNCINTERVAL");
            if (accountname.equals(Listactivity.imapNotes2Account.GetAccountname())) {
                if (isSynced) {
                    // Display last sync date
                    DateFormat dateFormat =
                        android.text.format.DateFormat.getDateFormat(getApplicationContext());
                    Date date = new Date();
                    String sdate = DateFormat.getDateTimeInstance(DateFormat.SHORT,DateFormat.SHORT).format(date);
                    String sinterval = " (interval:" + String.valueOf(syncInterval) + " min)";
                    status.setText("Last sync: " + sdate + sinterval);
                } else {
                    status.setText(OldStatus);
                }

                if (isChanged) {
                    if (Listactivity.storedNotes == null)
                         storedNotes = new NotesDb(getApplicationContext());
                    storedNotes.OpenDb();
                    storedNotes.GetStoredNotes(noteList, accountname);
                    listToView.notifyDataSetChanged();
                    storedNotes.CloseDb();
                }
            }
        }
    };

    public void RefreshList(){
        ProgressDialog loadingDialog = ProgressDialog.show(this, "ImapNotes2" , "Refreshing notes list... ", true);

        new SyncThread().execute(this.imapFolder, Listactivity.imapNotes2Account, this.noteList, this.listToView, loadingDialog, this.storedNotes, this.getApplicationContext());
        status.setText("Welcome");
    }
    
    public void UpdateList(String suid, String noteBody, String color, String action){
        ProgressDialog loadingDialog = ProgressDialog.show(this, "imapnote2" , "Updating notes list... ", true);

        new UpdateThread().execute(this.imapFolder, Listactivity.imapNotes2Account, this.noteList, this.listToView, loadingDialog, suid, noteBody, color, this.getApplicationContext(), action, this.storedNotes);

    }
    
    public boolean onCreateOptionsMenu(Menu menu){
    getMenuInflater().inflate(R.menu.list, menu);
    
    // Associate searchable configuration with the SearchView
    SearchManager searchManager =
           (SearchManager) getSystemService(Context.SEARCH_SERVICE);
    SearchView searchView =
            (SearchView) menu.findItem(R.id.search).getActionView();
    searchView.setSearchableInfo(
            searchManager.getSearchableInfo(getComponentName()));
     SearchView.OnQueryTextListener textChangeListener = new SearchView.OnQueryTextListener() {
         @Override
         public boolean onQueryTextChange(String newText) {
             // this is your adapter that will be filtered
             listToView.getFilter().filter(newText);
             return true;
         }

         @Override
         public boolean onQueryTextSubmit(String query) {
             // this is your adapter that will be filtered
             listToView.getFilter().filter(query);
             return true;
         }
     };
     searchView.setOnQueryTextListener(textChangeListener);

    return true;
    }
    
    public boolean onOptionsItemSelected (MenuItem item){
    switch (item.getItemId()){
        case R.id.login:
            Intent res = new Intent();
            String mPackage = "com.Pau.ImapNotes2";
            String mClass = ".AccontConfigurationActivity";
            res.setComponent(new ComponentName(mPackage,mPackage+mClass));
            res.putExtra("action", "CREATE_ACCOUNT");
            startActivity(res);
            return true;
        case R.id.refresh:
            this.TriggerSync(this.status);
            return true;
        case R.id.newnote:
            Intent toNew = new Intent(this, NewNoteActivity.class);
            toNew.putExtra("usesSticky", Listactivity.imapNotes2Account.GetUsesticky());
            startActivityForResult(toNew,Listactivity.NEW_BUTTON);
            return true;
        case R.id.about:
            try {
                ComponentName comp = new ComponentName(this.getApplicationContext(), Listactivity.class);
                PackageInfo pinfo = this.getApplicationContext().getPackageManager().getPackageInfo(comp.getPackageName(), 0);
                String versionName = "Version: " + pinfo.versionName;
                String versionCode = "Code: " + String.valueOf(pinfo.versionCode);

                new AlertDialog.Builder(this)
                    .setTitle("About ImapNotes2")
                    .setMessage(versionName + "\n" + versionCode)
                    .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int which) { 
                                // Do nothing
                            }
                         })
                    .show();
            } catch (android.content.pm.PackageManager.NameNotFoundException e) {
                Log.d("XXXXX","except");
            }
            return true;
        default:
            return super.onOptionsItemSelected(item);
    }
    }
    
    protected void onActivityResult(int requestCode, int resultCode, Intent data){ 
        switch(requestCode) {
            case Listactivity.SEE_DETAIL:
            // Returning from NoteDetailActivity
            if (resultCode == Listactivity.DELETE_BUTTON) {
                // Delete Message asked for
                // String suid will contain the Message Imap UID to delete
                String suid = data.getStringExtra("DELETE_ITEM_NUM_IMAP");
                this.UpdateList(suid, null, null, "delete");
            }
            if (resultCode == Listactivity.EDIT_BUTTON) {
                String txt = data.getStringExtra("EDIT_ITEM_TXT");
                String suid = data.getStringExtra("EDIT_ITEM_NUM_IMAP");
                String color = data.getStringExtra("EDIT_ITEM_COLOR");
                //Log.d(TAG,"Received request to delete message:"+suid);
                //Log.d(TAG,"Received request to replace message with:"+txt);
                this.UpdateList(suid, txt, color, "update");
            }
            case Listactivity.NEW_BUTTON:
            // Returning from NewNoteActivity
            if (resultCode == Listactivity.SAVE_BUTTON) {
                String res = data.getStringExtra("SAVE_ITEM");
                //Log.d(TAG,"Received request to save message:"+res);
                String color = data.getStringExtra("SAVE_ITEM_COLOR");
                this.UpdateList(null, res, color, "insert");
            }
        }
    }

    // Spinner item selected listener
    @Override
    public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
        ((TextView) this.accountSpinner.getSelectedView()).setBackgroundColor(0xFFB6B6B6);
        Account account = Listactivity.accounts[pos];
        // Check periodic sync. If set to 86400 (once a day), set it to 900 (15 minutes)
        // this is due to bad upgrade to v4 which handles offline mode and syncing
        // Remove this code after V4.0 if version no more used
        List<PeriodicSync> currentSyncs = ContentResolver.getPeriodicSyncs (account, AUTHORITY);
        for (PeriodicSync onesync : currentSyncs) {
            if (onesync.period == 86400) {
                ContentResolver.setIsSyncable(account, AUTHORITY, 1);
                ContentResolver.setSyncAutomatically(account, AUTHORITY, true);
                ContentResolver.addPeriodicSync(account, AUTHORITY, new Bundle(), 60);
                Toast.makeText(getApplicationContext(), "Recreating this account is recommended to manage sync interval. Set to 15 minutes in the meantime",
                        Toast.LENGTH_LONG).show();
            }
        }
        // End of code
        Listactivity.imapNotes2Account.SetAccountname(account.name);
        Listactivity.imapNotes2Account.SetUsername(Listactivity.accountManager.getUserData (account, "username"));
        String pwd = Listactivity.accountManager.getPassword(account);
        Listactivity.imapNotes2Account.SetPassword(pwd);
        Listactivity.imapNotes2Account.SetServer(Listactivity.accountManager.getUserData (account, "server"));
        Listactivity.imapNotes2Account.SetPortnum(Listactivity.accountManager.getUserData (account, "portnum"));
        Listactivity.imapNotes2Account.SetSecurity(Listactivity.accountManager.getUserData (account, "security"));
        Listactivity.imapNotes2Account.SetUsesticky(accountManager.getUserData (account, "usesticky"));
        Listactivity.imapNotes2Account.SetSyncinterval(Listactivity.accountManager.getUserData (account, "syncinterval"));
        Listactivity.imapNotes2Account.SetaccountHasChanged();
        Listactivity.imapNotes2Account.SetAccount(account);
        this.RefreshList();
    }
    
    @Override
    public void onNothingSelected(AdapterView<?> parent) {
        // TODO Auto-generated method stub
        
    }

    private void updateAccountSpinner () {

        this.spinnerList.notifyDataSetChanged();
        //this.accountSpinner.setSelection(spinnerList.getPosition(currentAccountname));
        if (this.accountSpinner.getSelectedItemId() == android.widget.AdapterView.INVALID_ROW_ID) {
        this.accountSpinner.setSelection(0);
        }
    
        if (Listactivity.currentList.size() == 1) {
            Account account = Listactivity.accounts[0];
            Listactivity.imapNotes2Account.SetUsername(Listactivity.accountManager.getUserData (account, "username"));
            String pwd = Listactivity.accountManager.getPassword(account);
            Listactivity.imapNotes2Account.SetPassword(pwd);
            Listactivity.imapNotes2Account.SetServer(Listactivity.accountManager.getUserData (account, "server"));
            Listactivity.imapNotes2Account.SetPortnum(Listactivity.accountManager.getUserData (account, "portnum"));
            Listactivity.imapNotes2Account.SetSecurity(Listactivity.accountManager.getUserData (account, "security"));
            Listactivity.imapNotes2Account.SetUsesticky(accountManager.getUserData (account, "usesticky"));
            Listactivity.imapNotes2Account.SetSyncinterval(Listactivity.accountManager.getUserData (account, "syncinterval"));
            Listactivity.imapNotes2Account.SetaccountHasChanged();
        }
    }

    private class AccountsUpdateListener implements OnAccountsUpdateListener {
        private ArrayList<Account> newAccounts;
        
        @Override
        public void onAccountsUpdated(Account[] accounts) {
            List<String> newList;
            Integer newListSize = 0;
            //invoked when the AccountManager starts up and whenever the account set changes
            this.newAccounts = new ArrayList<Account>();
            for (final Account account : accounts) {
                if (account.type.equals("com.Pau.ImapNotes2")) {
                    this.newAccounts.add(account);
                }
            }
            if (this.newAccounts.size() > 0) {
                Account[] imapNotes2Accounts = new Account[this.newAccounts.size()] ;
                int i = 0;
                for (final Account account : this.newAccounts) {
                    imapNotes2Accounts[i] = account;
                    i++;
                }
                Listactivity.accounts = imapNotes2Accounts;
                newList = new ArrayList<String>();
                for (Account account: Listactivity.accounts ) {
                    newList.add(account.name);
                }
                if (newList.size() == 0) return;
        
                Boolean equalLists = true;
                ListIterator<String> iter = Listactivity.currentList.listIterator();
                while(iter.hasNext()){
                    String s = iter.next();
                    if (!(newList.contains(s))) {
                        iter.remove();
                        String stringDir = (ImapNotes2.getAppContext()).getFilesDir() + "/" + s;
                        try {
                            FileUtils.deleteDirectory(new File (stringDir));
                        } catch (IOException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                        equalLists = false;
                    }
                }
                for (String accountName: newList ) {
                    if (!(Listactivity.currentList.contains(accountName))) {
                        Listactivity.currentList.add(accountName);
                        SyncUtils.CreateDirs (accountName, ImapNotes2.getAppContext());
        
                        equalLists = false;
                    }
                }
                if (equalLists) return;
                updateAccountSpinner();
            } else {
                File filesDir = (ImapNotes2.getAppContext()).getFilesDir();
                try {
                    FileUtils.cleanDirectory(filesDir);
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                Intent res = new Intent();
                String mPackage = "com.Pau.ImapNotes2";
                String mClass = ".AccontConfigurationActivity";
                res.setComponent(new ComponentName(mPackage,mPackage+mClass));
                startActivity(res);
            }
        }
    }

    // In case of neccessary debug  with user approval
    // This function will be called from onDestroy
    public void SendLogcatMail(){
        String emailData="";
        try {
          Process process = Runtime.getRuntime().exec("logcat -d");
          BufferedReader bufferedReader = new BufferedReader(
          new InputStreamReader(process.getInputStream()));
    
          StringBuilder sb=new StringBuilder();
          String line;
          while ((line = bufferedReader.readLine()) != null) {
            sb.append(line + "\n");
          }
          emailData=sb.toString();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    
        //send file using email
        Intent emailIntent = new Intent(Intent.ACTION_SEND);
        String to[] = {"[email protected]"};
        emailIntent .putExtra(Intent.EXTRA_EMAIL, to);
        // the attachment
        emailIntent .putExtra(Intent.EXTRA_TEXT, emailData);
        // the mail subject
        emailIntent .putExtra(Intent.EXTRA_SUBJECT, "Logcat content for ImapNotes2 debugging");
        emailIntent.setType("message/rfc822");
        startActivity(Intent.createChooser(emailIntent , "Send email..."));
    }

    public static void TriggerSync(TextView statusField) {
        OldStatus=statusField.getText().toString();
        statusField.setText("Syncing...");
        Account mAccount = Listactivity.imapNotes2Account.GetAccount();
        Bundle settingsBundle = new Bundle();
        settingsBundle.putBoolean(
                ContentResolver.SYNC_EXTRAS_MANUAL, true);
        settingsBundle.putBoolean(
                ContentResolver.SYNC_EXTRAS_EXPEDITED, true);
        //Log.d(TAG,"Request a sync for:"+mAccount);
        ContentResolver.requestSync(mAccount, AUTHORITY, settingsBundle);
    }

	@Override
	public Filter getFilter() {
		return null;
	}
}