package com.example.wordbook.provider;

import android.app.SearchManager;
import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.provider.BaseColumns;
import android.text.TextUtils;

/**
 * コンテンツプロバイダ
 */
public class WBProvider extends ContentProvider {

	/** 識別子 */
	public static final String AUTHORITY = "com.example.wordbook.wbprovider";

	/** コンテンツURI */
	public static final Uri INFO_CONTENT_URI = Uri.parse("content://"
			+ AUTHORITY + "/" + WBData.TABLE_NAME_INFO);

	/** コンテンツ MIME type */
	public static final String INFO_CONTENT_TYPE = "vnd.android.cursor.dir/vnd.wordbook.info";

	/** コンテンツアイテム MIME type */
	public static final String INFO_CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.wordbook.info";

	/** コンテンツ */
	private static final int WBDATA_INFO = 1;

	/** コンテンツアイテム */
	private static final int WBDATA_INFO_ITEM = 2;

	/** SEARCH_SUGGEST */
	private static final int SEARCH_SUGGEST = 3;

	/** SHORTCUT_REFRESH */
	private static final int SHORTCUT_REFRESH = 4;

	/** URIマッチャー */
	private static final UriMatcher URI_MATCHER;

	/** URIマッチャー初期化 */
	static {
		URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
		URI_MATCHER.addURI(AUTHORITY, WBData.TABLE_NAME_INFO, WBDATA_INFO);
		URI_MATCHER.addURI(AUTHORITY, WBData.TABLE_NAME_INFO + "/#",
				WBDATA_INFO_ITEM);
		URI_MATCHER.addURI(AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY,
				SEARCH_SUGGEST);
		URI_MATCHER.addURI(AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY
				+ "/*", SEARCH_SUGGEST);
		URI_MATCHER.addURI(AUTHORITY, SearchManager.SUGGEST_URI_PATH_SHORTCUT,
				SHORTCUT_REFRESH);
		URI_MATCHER.addURI(AUTHORITY, SearchManager.SUGGEST_URI_PATH_SHORTCUT
				+ "/*", SHORTCUT_REFRESH);
	}

	/** Helper */
	private WBHelper mHelper;

	/**
	 * コンテンツタイプ取得処理
	 * 
	 * @param uri
	 *            コンテンツURI
	 * @return コンテンツタイプ
	 */
	@Override
	public String getType(Uri uri) {
		if (uri == null) {
			throw new IllegalArgumentException("NULL parameter");
		}

		switch (URI_MATCHER.match(uri)) {
		case WBDATA_INFO:
			return INFO_CONTENT_TYPE;
		case WBDATA_INFO_ITEM:
			return INFO_CONTENT_ITEM_TYPE;
		case SEARCH_SUGGEST:
			return SearchManager.SUGGEST_MIME_TYPE;
		case SHORTCUT_REFRESH:
			return SearchManager.SHORTCUT_MIME_TYPE;
		default:
			throw new IllegalArgumentException("Unknown URI:" + uri);
		}
	}

	/**
	 * Helper生成処理
	 * 
	 * @return true
	 */
	@Override
	public boolean onCreate() {
		mHelper = WBHelper.getInstance(getContext());
		return true;
	}

	/**
	 * 挿入処理
	 * 
	 * @param uri
	 *            Insert対象URI
	 * @param values
	 *            Insert値
	 * @return 挿入結果URI
	 */
	@Override
	public Uri insert(Uri uri, ContentValues values) {
		if (uri == null || values == null) {
			throw new IllegalArgumentException("NULL parameter");
		}

		switch (URI_MATCHER.match(uri)) {
		case WBDATA_INFO:
			SQLiteDatabase db = mHelper.getWritableDatabase();
			long id = db.insert(WBData.TABLE_NAME_INFO, null, values);
			if (id > 0) {
				// インサートが成功した場合はURIにIDを付加して返却
				Uri retUri = ContentUris.withAppendedId(INFO_CONTENT_URI, id);
				// 通知
				getContext().getContentResolver().notifyChange(retUri, null);
				return retUri;
			}
			throw new SQLException("Insert failed:" + uri);
		default:
			throw new IllegalArgumentException("Unsupported URI:" + uri);
		}
	}

	/**
	 * 削除処理
	 * 
	 * @param uri
	 *            Delete対象URI
	 * @param selection
	 *            Where句
	 * @param selectionArgs
	 *            Where句で ? を使用する際の置換値
	 * @return 削除件数
	 */
	@Override
	public int delete(Uri uri, String selection, String[] selectionArgs) {
		if (uri == null) {
			throw new IllegalArgumentException("NULL parameter");
		}

		int count = 0;
		SQLiteDatabase db = mHelper.getWritableDatabase();
		switch (URI_MATCHER.match(uri)) {
		case WBDATA_INFO:
			count = db.delete(WBData.TABLE_NAME_INFO, selection, selectionArgs);
			break;
		case WBDATA_INFO_ITEM:
			long id = ContentUris.parseId(uri);
			count = db.delete(WBData.TABLE_NAME_INFO, BaseColumns._ID
					+ "="
					+ id
					+ (!TextUtils.isEmpty(selection) ? " AND (" + selection
							+ ")" : ""), selectionArgs);
			break;
		default:
			throw new IllegalArgumentException("Unsupported URI:" + uri);
		}

		// 通知
		getContext().getContentResolver().notifyChange(uri, null);

		return count;
	}

	/**
	 * 更新処理
	 * 
	 * @param uri
	 *            Update対象URI
	 * @param values
	 *            Update値
	 * @param selection
	 *            Where句
	 * @param selectionArgs
	 *            Where句で ? を使用する際の置換値
	 * @return 更新件数
	 */
	@Override
	public int update(Uri uri, ContentValues values, String selection,
			String[] selectionArgs) {
		if (uri == null || values == null) {
			throw new IllegalArgumentException("NULL parameter");
		}

		int count = 0;
		SQLiteDatabase db = mHelper.getWritableDatabase();
		switch (URI_MATCHER.match(uri)) {
		case WBDATA_INFO:
			count = db.update(WBData.TABLE_NAME_INFO, values, selection,
					selectionArgs);
			break;
		case WBDATA_INFO_ITEM:
			long id = ContentUris.parseId(uri);
			count = db.update(WBData.TABLE_NAME_INFO, values, BaseColumns._ID
					+ "="
					+ id
					+ (!TextUtils.isEmpty(selection) ? " AND (" + selection
							+ ")" : ""), selectionArgs);
			break;
		default:
			throw new IllegalArgumentException("Unsupported URI:" + uri);
		}

		// 通知
		getContext().getContentResolver().notifyChange(uri, null);

		return count;
	}

	/**
	 * クエリ発行処理
	 * 
	 * @param uri
	 *            対象URI
	 * @param projection
	 *            取得列名配列
	 * @param selection
	 *            Where句
	 * @param selectionArgs
	 *            Where句で ? を使用する際の置換値
	 * @param sortOrder
	 *            OrderBy句
	 * @return クエリ結果カーソルオブジェクト
	 */
	@Override
	public Cursor query(Uri uri, String[] projection, String selection,
			String[] selectionArgs, String sortOrder) {
		if (uri == null) {
			throw new IllegalArgumentException("NULL parameter");
		}

		// ソート順序
		String order = sortOrder;
		if (TextUtils.isEmpty(sortOrder)) {
			order = WBData.InfoColumns.DEFAULT_SORT_ORDER;
		}
		// 取得数制限
		String limit = uri.getQueryParameter("limit");

		// クエリ生成
		SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
		qb.setTables(WBData.TABLE_NAME_INFO);
		qb.setProjectionMap(WBData.PROJECTION_MAP_INFO);

		SQLiteDatabase db = mHelper.getReadableDatabase();
		switch (URI_MATCHER.match(uri)) {
		case WBDATA_INFO:
			// 通常クエリ対応
			break;
		case WBDATA_INFO_ITEM:
			// 通常クエリ対応
			long id = ContentUris.parseId(uri);
			qb.appendWhere(BaseColumns._ID + "=" + id);
			break;
		case SEARCH_SUGGEST:
			// QSBクエリ対応

			// selectionは未使用
			// 検索欄の値が質問か解答に含まれるデータを検索
			StringBuilder sb = new StringBuilder();
			sb.append(WBData.InfoColumns.INFO_QUESTION);
			sb.append(" LIKE '%'||?||'%'");
			sb.append(" OR ");
			sb.append(WBData.InfoColumns.INFO_ANSWER);
			sb.append(" LIKE '%'||?||'%'");
			String[] args = { selectionArgs[0], selectionArgs[0] };

			Cursor c = qb.query(db, projection, sb.toString(), args, null,
					null, order, limit);
			// QSBクエリ用カーソル
			Cursor qsbc = makeWordbookQBSCursor(c);
			c.close();

			return qsbc;
		case SHORTCUT_REFRESH:
			// QSBクエリ対応
			return null;
		default:
			throw new IllegalArgumentException("Unsupported URI:" + uri);
		}

		// 通常クエリ用カーソル
		Cursor c = qb.query(db, projection, selection, selectionArgs, null,
				null, order, limit);

		// 通知
		c.setNotificationUri(getContext().getContentResolver(), uri);

		return c;
	}

	/** QSBクエリ用カーソル列名 */
	private static final String[] SUGGEST_COLUMNS = { BaseColumns._ID, // 必須
			SearchManager.SUGGEST_COLUMN_SHORTCUT_ID, // 履歴
			SearchManager.SUGGEST_COLUMN_TEXT_1, // 質問
			SearchManager.SUGGEST_COLUMN_TEXT_2, // 解答
			SearchManager.SUGGEST_COLUMN_INTENT_DATA, // 識別用データ
	};

	/**
	 * QSBクエリ用カーソル生成
	 * 
	 * @param c
	 *            検索結果
	 * @return　QSBクエリ用検索結果
	 */
	private Cursor makeWordbookQBSCursor(Cursor c) {
		MatrixCursor qsb = new MatrixCursor(SUGGEST_COLUMNS);

		int idx_num, idx_q, idx_a;
		idx_num = c.getColumnIndex(WBData.InfoColumns.INFO_NUM);
		idx_q = c.getColumnIndex(WBData.InfoColumns.INFO_QUESTION);
		idx_a = c.getColumnIndex(WBData.InfoColumns.INFO_ANSWER);
		if (c.moveToFirst()) {
			do {
				qsb.addRow(new Object[] { c.getInt(idx_num), // INFO_NUM
						SearchManager.SUGGEST_NEVER_MAKE_SHORTCUT, // 履歴無効
						c.getString(idx_q), // 質問
						c.getString(idx_a), // 解答
						c.getString(idx_q) + "," + c.getString(idx_a), // 識別用データ
				});
			} while (c.moveToNext());
		}

		return qsb;
	}

}
