/*
 * Copyright (C) 2012 Brian Muramatsu
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.btmura.android.reddit.provider;

import java.io.IOException;
import java.util.ArrayList;

import android.content.ContentValues;
import android.database.DatabaseUtils.InsertHelper;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;

import com.btmura.android.reddit.BuildConfig;
import com.btmura.android.reddit.database.Kinds;
import com.btmura.android.reddit.database.Sessions;
import com.btmura.android.reddit.database.SharedColumns;
import com.btmura.android.reddit.util.Array;

/**
 * {@link BaseProvider} that has additional methods for handling sessions.
 */
abstract class SessionProvider extends BaseProvider {

    private static final String SELECT_MORE_WITH_SESSION_ID =
            Kinds.COLUMN_KIND + "=" + Kinds.KIND_MORE
                    + " AND " + SharedColumns.COLUMN_SESSION_ID + "=?";

    SessionProvider(String logTag) {
        super(logTag);
    }

    /** Returns a session id pointing to the data. */
    long getListingSession(Listing listing, SQLiteDatabase db, long sessionId) throws IOException {
        // Return existing session if it exists and we're not appending more to
        // it.
        if (sessionId != -1 && !listing.isAppend()) {
            return sessionId;
        }

        // Fetch values to insert from the network.
        ArrayList<ContentValues> values = listing.getValues();

        // Insert new db values. Delete prior existing session.
        db.beginTransaction();
        try {
            // Create a new session if there is no id.
            if (sessionId == -1) {
                ContentValues v = new ContentValues(1);
                v.put(Sessions.COLUMN_TIMESTAMP, System.currentTimeMillis());
                sessionId = db.insert(Sessions.TABLE_NAME, null, v);
            }

            // Delete any existing "Loading..." signs if appending.
            if (listing.isAppend()) {
                db.delete(listing.getTargetTable(), SELECT_MORE_WITH_SESSION_ID,
                        Array.of(sessionId));
            }

            // Add the session id to the data rows.
            int count = values.size();
            for (int i = 0; i < count; i++) {
                values.get(i).put(SharedColumns.COLUMN_SESSION_ID, sessionId);
            }

            // Insert the rows into the database.
            InsertHelper helper = new InsertHelper(db, listing.getTargetTable());
            for (int i = 0; i < count; i++) {
                helper.insert(values.get(i));
            }
            db.setTransactionSuccessful();

            if (BuildConfig.DEBUG) {
                Log.d(logTag, "created new session: " + sessionId);
            }

            return sessionId;
        } finally {
            db.endTransaction();
        }
    }
}

@@ -1741,25 +1741,8 @@
 more
- to%0A        // it
 .%0A  
@@ -1986,39 +1986,8 @@
 ues.
- Delete prior existing session.
 %0A   
@@ -2047,286 +2047,275 @@
  // 
-Create a new session if there is no id.%0A            if (sessionId == -1) %7B%0A                ContentValues v = new ContentValues(1);%0A                v.put(Sessions.COLUMN_TIMESTAMP, System.currentTimeMillis());%0A                sessionId = db.insert(Sessions.TABLE_NAME, null, v);%0A
+Delete any existing %22Loading...%22 signs if appending.%0A            if (listing.isAppend()) %7B%0A                // Appending requires an existing session to append the data.%0A                if (sessionId == -1) %7B%0A                    throw new IllegalStateException();%0A    
     
@@ -2329,32 +2329,36 @@
  %7D%0A%0A            
+    
 // Delete any ex
@@ -2355,91 +2355,215 @@
 ete 
-any existing %22Loading...%22 signs if appending.%0A            if (listing.isAppend()) %7B
+the row for this append. If there is no such row, then%0A                // this might be a duplicate append that got triggered, so just%0A                // return the existing session id and hope for the best.
 %0A   
@@ -2570,24 +2570,36 @@
             
+ int count =
  db.delete(l
@@ -2622,16 +2622,40 @@
 Table(),
+%0A                       
  SELECT_
@@ -2679,52 +2679,426 @@
 _ID,
-%0A                        Array.of(sessionId)
+ Array.of(sessionId));%0A                if (count == 0) %7B%0A                    return sessionId;%0A                %7D%0A            %7D%0A%0A            // Create a new session if there is no id.%0A            if (sessionId == -1) %7B%0A                ContentValues v = new ContentValues(1);%0A                v.put(Sessions.COLUMN_TIMESTAMP, System.currentTimeMillis());%0A                sessionId = db.insert(Sessions.TABLE_NAME, null, v
 );%0A 

Fix a possibility of duplicate rows