/*
 * Copyright (C) 2016 Google Inc.
 *
 * 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.googlecode.android_scripting.facade;

import android.app.Service;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.provider.ContactsContract;

import com.googlecode.android_scripting.jsonrpc.RpcReceiver;
import com.googlecode.android_scripting.rpc.Rpc;
import com.googlecode.android_scripting.rpc.RpcOptional;
import com.googlecode.android_scripting.rpc.RpcParameter;

import java.util.ArrayList;
import java.util.List;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

/**
 * Provides access to contacts related functionality.
 *
 * @author MeanEYE.rcf (meaneye.rcf@gmail.com
 */
public class ContactsFacade extends RpcReceiver {
  private static final Uri CONTACTS_URI = Uri.parse("content://contacts/people");
  private final ContentResolver mContentResolver;
  private final Service mService;
  private final CommonIntentsFacade mCommonIntentsFacade;
  public Uri mPhoneContent = null;
  public String mContactId;
  public String mPrimary;
  public String mPhoneNumber;
  public String mHasPhoneNumber;

  public ContactsFacade(FacadeManager manager) {
    super(manager);
    mService = manager.getService();
    mContentResolver = mService.getContentResolver();
    mCommonIntentsFacade = manager.getReceiver(CommonIntentsFacade.class);
    try {
      // Backward compatibility... get contract stuff using reflection
      Class<?> phone = Class.forName("android.provider.ContactsContract$CommonDataKinds$Phone");
      mPhoneContent = (Uri) phone.getField("CONTENT_URI").get(null);
      mContactId = (String) phone.getField("CONTACT_ID").get(null);
      mPrimary = (String) phone.getField("IS_PRIMARY").get(null);
      mPhoneNumber = (String) phone.getField("NUMBER").get(null);
      mHasPhoneNumber = (String) phone.getField("HAS_PHONE_NUMBER").get(null);
    } catch (Exception e) {
    }
  }

  private Uri buildUri(Integer id) {
    Uri uri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, id);
    return uri;
  }

  @Rpc(description = "Displays a list of contacts to pick from.", returns = "A map of result values.")
  public Intent pickContact() throws JSONException {
    return mCommonIntentsFacade.pick("content://contacts/people");
  }

  @Rpc(description = "Displays a list of phone numbers to pick from.", returns = "The selected phone number.")
  public String pickPhone() throws JSONException {
    String result = null;
    Intent data = mCommonIntentsFacade.pick("content://contacts/phones");
    if (data != null) {
      Uri phoneData = data.getData();
      Cursor cursor = mService.getContentResolver().query(phoneData, null, null, null, null);
      if (cursor != null) {
        if (cursor.moveToFirst()) {
          result = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.PhoneLookup.NUMBER));
        }
        cursor.close();
      }
    }
    return result;
  }

  @Rpc(description = "Returns a List of all possible attributes for contacts.")
  public List<String> contactsGetAttributes() {
    List<String> result = new ArrayList<String>();
    Cursor cursor = mContentResolver.query(CONTACTS_URI, null, null, null, null);
    if (cursor != null) {
      String[] columns = cursor.getColumnNames();
      for (int i = 0; i < columns.length; i++) {
        result.add(columns[i]);
      }
      cursor.close();
    }
    return result;
  }

  // TODO(MeanEYE.rcf): Add ability to narrow selection by providing named pairs of attributes.
  @Rpc(description = "Returns a List of all contact IDs.")
  public List<Integer> contactsGetIds() {
    List<Integer> result = new ArrayList<Integer>();
    String[] columns = { "_id" };
    Cursor cursor = mContentResolver.query(CONTACTS_URI, columns, null, null, null);
    if (cursor != null) {
      while (cursor.moveToNext()) {
        result.add(cursor.getInt(0));
      }
      cursor.close();
    }
    return result;
  }

  @Rpc(description = "Returns a List of all contacts.", returns = "a List of contacts as Maps")
  public List<JSONObject> contactsGet(
      @RpcParameter(name = "attributes") @RpcOptional JSONArray attributes) throws JSONException {
    List<JSONObject> result = new ArrayList<JSONObject>();
    String[] columns;
    if (attributes == null || attributes.length() == 0) {
      // In case no attributes are specified we set the default ones.
      columns = new String[] { "_id", "name", "primary_phone", "primary_email", "type" };
    } else {
      // Convert selected attributes list into usable string list.
      columns = new String[attributes.length()];
      for (int i = 0; i < attributes.length(); i++) {
        columns[i] = attributes.getString(i);
      }
    }
    List<String> queryList = new ArrayList<String>();
    for (String s : columns) {
      queryList.add(s);
    }
    if (!queryList.contains("_id")) {
      queryList.add("_id");
    }

    String[] query = queryList.toArray(new String[queryList.size()]);
    Cursor cursor = mContentResolver.query(CONTACTS_URI, query, null, null, null);
    if (cursor != null) {
      int idIndex = cursor.getColumnIndex("_id");
      while (cursor.moveToNext()) {
        String id = cursor.getString(idIndex);
        JSONObject message = new JSONObject();
        for (int i = 0; i < columns.length; i++) {
          String key = columns[i];
          String value = cursor.getString(cursor.getColumnIndex(key));
          if (mPhoneNumber != null) {
            if (key.equals("primary_phone")) {
              value = findPhone(id);
            }
          }
          message.put(key, value);
        }
        result.add(message);
      }
      cursor.close();
    }
    return result;
  }

  private String findPhone(String id) {
    String result = null;
    if (id == null || id.equals("")) {
      return result;
    }
    try {
      if (Integer.parseInt(id) > 0) {
        Cursor pCur =
            mContentResolver.query(mPhoneContent, new String[] { mPhoneNumber }, mContactId
                + " = ? and " + mPrimary + "=1", new String[] { id }, null);
        if (pCur != null) {
          pCur.getColumnNames();
          while (pCur.moveToNext()) {
            result = pCur.getString(0);
            break;
          }
        }
        pCur.close();
      }
    } catch (Exception e) {
      return null;
    }
    return result;
  }

  @Rpc(description = "Returns contacts by ID.")
  public JSONObject contactsGetById(@RpcParameter(name = "id") Integer id,
      @RpcParameter(name = "attributes") @RpcOptional JSONArray attributes) throws JSONException {
    JSONObject result = null;
    Uri uri = buildUri(id);
    String[] columns;
    if (attributes == null || attributes.length() == 0) {
      // In case no attributes are specified we set the default ones.
      columns = new String[] { "_id", "name", "primary_phone", "primary_email", "type" };
    } else {
      // Convert selected attributes list into usable string list.
      columns = new String[attributes.length()];
      for (int i = 0; i < attributes.length(); i++) {
        columns[i] = attributes.getString(i);
      }
    }
    Cursor cursor = mContentResolver.query(uri, columns, null, null, null);
    if (cursor != null) {
      result = new JSONObject();
      cursor.moveToFirst();
      for (int i = 0; i < columns.length; i++) {
        result.put(columns[i], cursor.getString(i));
      }
      cursor.close();
    }
    return result;
  }

  // TODO(MeanEYE.rcf): Add ability to narrow selection by providing named pairs of attributes.
  @Rpc(description = "Returns the number of contacts.")
  public Integer contactsGetCount() {
    Integer result = 0;
    Cursor cursor = mContentResolver.query(CONTACTS_URI, null, null, null, null);
    if (cursor != null) {
      result = cursor.getCount();
      cursor.close();
    }
    return result;
  }

  private String[] jsonToArray(JSONArray array) throws JSONException {
    String[] result = null;
    if (array != null && array.length() > 0) {
      result = new String[array.length()];
      for (int i = 0; i < array.length(); i++) {
        result[i] = array.getString(i);
      }
    }
    return result;
  }

  /**
   * Exactly as per <a href=
   * "http://developer.android.com/reference/android/content/ContentResolver.html#query%28android.net.Uri,%20java.lang.String[],%20java.lang.String,%20java.lang.String[],%20java.lang.String%29"
   * >ContentResolver.query</a>
   */
  @Rpc(description = "Content Resolver Query", returns = "result of query as Maps")
  public List<JSONObject> queryContent(
      @RpcParameter(name = "uri", description = "The URI, using the content:// scheme, for the content to retrieve.") String uri,
      @RpcParameter(name = "attributes", description = "A list of which columns to return. Passing null will return all columns") @RpcOptional JSONArray attributes,
      @RpcParameter(name = "selection", description = "A filter declaring which rows to return") @RpcOptional String selection,
      @RpcParameter(name = "selectionArgs", description = "You may include ?s in selection, which will be replaced by the values from selectionArgs") @RpcOptional JSONArray selectionArgs,
      @RpcParameter(name = "order", description = "How to order the rows") @RpcOptional String order)
      throws JSONException {
    List<JSONObject> result = new ArrayList<JSONObject>();
    String[] columns = jsonToArray(attributes);
    String[] args = jsonToArray(selectionArgs);
    Cursor cursor = mContentResolver.query(Uri.parse(uri), columns, selection, args, order);
    if (cursor != null) {
      String[] names = cursor.getColumnNames();
      while (cursor.moveToNext()) {
        JSONObject message = new JSONObject();
        for (int i = 0; i < cursor.getColumnCount(); i++) {
          String key = names[i];
          String value = cursor.getString(i);
          message.put(key, value);
        }
        result.add(message);
      }
      cursor.close();
    }
    return result;
  }

  @Rpc(description = "Content Resolver Query Attributes", returns = "a list of available columns for a given content uri")
  public JSONArray queryAttributes(
      @RpcParameter(name = "uri", description = "The URI, using the content:// scheme, for the content to retrieve.") String uri)
      throws JSONException {
    JSONArray result = new JSONArray();
    Cursor cursor = mContentResolver.query(Uri.parse(uri), null, "1=0", null, null);
    if (cursor != null) {
      String[] names = cursor.getColumnNames();
      for (String name : names) {
        result.put(name);
      }
      cursor.close();
    }
    return result;
  }

  @Override
  public void shutdown() {
  }
}
