package com.czbix.v2ex.dao;

import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteQueryBuilder;
import android.support.annotation.Nullable;

import com.czbix.v2ex.model.Avatar;
import com.czbix.v2ex.model.Node;
import com.google.common.base.Preconditions;

public class NodeDAO {
    private static final String TABLE_NAME = "node";

    private static final String KEY_ID = "id";
    private static final String KEY_NAME = "name";
    private static final String KEY_TITLE = "title";
    // meaning alternative
    private static final String KEY_ALT = "alt";
    private static final String KEY_AVATAR = "avatar";

    private static final String[] SCHEMA = {KEY_ID, KEY_NAME, KEY_TITLE, KEY_ALT, KEY_AVATAR};

    private static final String SQL_GET_BY_NAME = SQLiteQueryBuilder.buildQueryString(false,
            TABLE_NAME, SCHEMA, KEY_NAME + " = ?", null, null, null ,null);

    public static void createTable(SQLiteDatabase db) {
        Preconditions.checkState(db.inTransaction(), "create table must be in transaction");

        String sql = "CREATE TABLE " + TABLE_NAME + "("
                + KEY_ID + " INTEGER PRIMARY KEY,"
                + KEY_NAME + " TEXT UNIQUE NOT NULL,"
                + KEY_TITLE + " TEXT NOT NULL,"
                + KEY_ALT + " TEXT,"
                + KEY_AVATAR + " TEXT"
                + ")";

        db.execSQL(sql);

        sql = "CREATE UNIQUE INDEX index_name ON " + TABLE_NAME + "("
                + KEY_NAME + ")";
        db.execSQL(sql);
    }

    @Nullable
    public static Node get(String name) {
        final SQLiteDatabase db = getReadDb();
        Cursor cursor = null;
        try {
            cursor = db.rawQuery(SQL_GET_BY_NAME, new String[]{name});
            if (!cursor.moveToFirst()) {
                return null;
            }

            Node.Builder builder = new Node.Builder();
            builder.setId(cursor.getInt(0))
                    .setName(cursor.getString(1))
                    .setTitle(cursor.getString(2))
                    .setTitleAlternative(cursor.getString(3));
            final Avatar avatar = new Avatar.Builder().setBaseUrl(cursor.getString(4)).createAvatar();
            builder.setAvatar(avatar);

            return builder.createNode();
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }
    }

    private static SQLiteDatabase getWriteDb() {
        return V2exDb.getInstance().getWritableDatabase();
    }

    private static SQLiteDatabase getReadDb() {
        return V2exDb.getInstance().getReadableDatabase();
    }

    public static void insert(Node node) {
        final SQLiteDatabase db = getWriteDb();
        final ContentValues values = new ContentValues(5);
        values.put(KEY_ID, node.getId());
        values.put(KEY_NAME, node.getName());
        values.put(KEY_TITLE, node.getTitle());
        values.put(KEY_ALT, node.getAlternative());
        values.put(KEY_AVATAR, node.getAvatar().getBaseUrl());

        db.insertWithOnConflict(TABLE_NAME, null, values, SQLiteDatabase.CONFLICT_REPLACE);
    }
}

@@ -233,16 +233,46 @@
 ullable;
+%0Aimport android.util.LruCache;
 %0A%0Aimport
@@ -1003,24 +1003,91 @@
 ll ,null);%0A%0A
+    private static final LruNodeCache CACHE = new LruNodeCache();%0A%0A
     public s
@@ -1747,24 +1747,129 @@
 ing name) %7B%0A
+        Node node = CACHE.getNode(name);%0A        if (node != null) %7B%0A            return node;%0A        %7D%0A%0A
         fina
@@ -2521,22 +2521,22 @@
         
-return
+node =
  builder
@@ -2546,24 +2546,89 @@
 eateNode();%0A
+            CACHE.putNode(name, node);%0A%0A            return node;%0A
         %7D fi
@@ -3359,24 +3359,24 @@
 aseUrl());%0A%0A
-
         db.i
@@ -3460,11 +3460,443 @@
 );%0A    %7D
+%0A%0A    public static class LruNodeCache %7B%0A        private final LruCache%3CString, Node%3E mLruCache;%0A%0A        public LruNodeCache() %7B%0A            final int cacheSize = 32;%0A            mLruCache = new LruCache%3C%3E(cacheSize);%0A        %7D%0A%0A        public Node getNode(String name) %7B%0A            return mLruCache.get(name);%0A        %7D%0A%0A        public void putNode(String name, Node node) %7B%0A            mLruCache.put(name, node);%0A        %7D%0A    %7D
 %0A%7D%0A

add cache for NodeDAO