/**
 * Copyright (C) 2010-2012 Regis Montoya (aka r3gis - www.r3gis.fr)
 * This file is part of CSipSimple.
 *
 *  CSipSimple is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *  If you own a pjsip commercial license you can also redistribute it
 *  and/or modify it under the terms of the GNU Lesser General Public License
 *  as an android library.
 *
 *  CSipSimple is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with CSipSimple.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.voiceblue.phone.ui.favorites;

import android.content.Context;
import android.database.ContentObserver;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.database.MergeCursor;
import android.provider.BaseColumns;
import android.support.v4.content.AsyncTaskLoader;
import android.text.TextUtils;

import com.voiceblue.phone.api.SipProfile;
import com.voiceblue.phone.utils.contacts.ContactsWrapper;

import java.util.ArrayList;

public class FavLoader extends AsyncTaskLoader<Cursor> {

    private Cursor currentResult;

    public FavLoader(Context context) {
        super(context);
    }
    

    private ContentObserver loaderObserver = new ForceLoadContentObserver();
    
    @Override
    public Cursor loadInBackground() {
        // First of all, get all active accounts
        ArrayList<SipProfile> accounts = SipProfile.getAllProfiles(getContext(), true,
                new String[] {
                        SipProfile.FIELD_ID,
                        SipProfile.FIELD_ACC_ID,
                        SipProfile.FIELD_ACTIVE,
                        SipProfile.FIELD_DISPLAY_NAME,
                        SipProfile.FIELD_WIZARD,
                        SipProfile.FIELD_PRIORITY,
                        SipProfile.FIELD_ANDROID_GROUP,
                        SipProfile.FIELD_PUBLISH_ENABLED,
                        SipProfile.FIELD_REG_URI,
                        SipProfile.FIELD_PROXY
                });

        Cursor[] cursorsToMerge = new Cursor[2 * accounts.size()];
        int i = 0;
        for (SipProfile acc : accounts) {
            cursorsToMerge[i++] = createHeaderCursorFor(acc);
            cursorsToMerge[i++] = createContentCursorFor(acc);
            
        }

        getContext().getContentResolver().registerContentObserver(SipProfile.ACCOUNT_STATUS_URI,
                true, loaderObserver);
        
        if(cursorsToMerge.length > 0) {
            MergeCursor mg = new MergeCursor(cursorsToMerge);
            mg.registerContentObserver(loaderObserver);
            return mg;
        }else {
            return null;
        }
    }

    /**
     * Called when there is new data to deliver to the client. The super class
     * will take care of delivering it; the implementation here just adds a
     * little more logic.
     */
    @Override
    public void deliverResult(Cursor c) {
        if (isReset()) {
            // An async query came in while the loader is stopped. We
            // don't need the result.
            if (currentResult != null) {
                onReleaseResources(currentResult);
            }
        }
        
        currentResult = c;

        if (isStarted()) {
            // If the Loader is currently started, we can immediately
            // deliver its results.
            super.deliverResult(c);
        }
    }

    /**
     * Handles a request to start the Loader.
     */
    @Override
    protected void onStartLoading() {
        if (currentResult != null && !takeContentChanged()) {
            // If we currently have a result available, deliver it
            // immediately.
            deliverResult(currentResult);
        }else {
            forceLoad();
        }
    }

    /**
     * Handles a request to stop the Loader.
     */
    @Override
    protected void onStopLoading() {
        // Attempt to cancel the current load task if possible.
        cancelLoad();
    }

    /**
     * Handles a request to cancel a load.
     */
    @Override
    public void onCanceled(Cursor c) {
        super.onCanceled(c);

        // At this point we can release the resources associated with 'apps'
        // if needed.
        onReleaseResources(c);
        
    }

    /**
     * Handles a request to completely reset the Loader.
     */
    @Override
    protected void onReset() {
        super.onReset();

        // Ensure the loader is stopped
        onStopLoading();

        // At this point we can release the resources associated with 'apps'
        // if needed.
        if (currentResult != null) {
            onReleaseResources(currentResult);
            currentResult = null;
        }
    }

    /**
     * Helper function to take care of releasing resources associated with an
     * actively loaded data set.
     */
    protected void onReleaseResources(Cursor c) {
        if(c != null) {
            c.unregisterContentObserver(loaderObserver);
            c.close();
        }

        getContext().getContentResolver().unregisterContentObserver(loaderObserver);
    }

    /**
     * Creates a cursor that contains a single row and maps the section to the
     * given value.
     */
    private Cursor createHeaderCursorFor(SipProfile account) {
        MatrixCursor matrixCursor =
                new MatrixCursor(new String[] {
                        BaseColumns._ID, 
                        ContactsWrapper.FIELD_TYPE,
                        SipProfile.FIELD_DISPLAY_NAME,
                        SipProfile.FIELD_WIZARD,
                        SipProfile.FIELD_ANDROID_GROUP,
                        SipProfile.FIELD_PUBLISH_ENABLED,
                        SipProfile.FIELD_REG_URI,
                        SipProfile.FIELD_PROXY,
                        SipProfile.FIELD_ACC_ID
                });
        String proxies = "";
        if(account.proxies != null) {
            proxies = TextUtils.join(SipProfile.PROXIES_SEPARATOR, account.proxies);
        }
        matrixCursor.addRow(new Object[] {
                account.id,
                ContactsWrapper.TYPE_GROUP,
                account.display_name,
                account.wizard,
                account.android_group,
                account.publish_enabled,
                account.reg_uri,
                proxies,
                account.acc_id
        });
        return matrixCursor;
    }

    /**
     * Creates a cursor that contains contacts group corresponding to an sip
     * account.
     */
    private Cursor createContentCursorFor(SipProfile account) {
        Cursor c = null;
        if(!TextUtils.isEmpty(account.android_group)) {
            c = ContactsWrapper.getInstance().getContactsByGroup(getContext(), account.android_group);
        }
        if(c != null) {
            return c;
        }
        MatrixCursor mc = new MatrixCursor (new String[] {
                BaseColumns._ID, 
                ContactsWrapper.FIELD_TYPE
        });
        mc.addRow(new Object[] {account.id, ContactsWrapper.TYPE_CONFIGURE});
        return mc;
    }

}
