/*
 * Copyright (C) 2009 University of Washington
 *
 * 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 org.odk.collect.android.widgets;

import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.provider.MediaStore.Audio;
import android.util.Log;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TableLayout;
import android.widget.Toast;

import org.javarosa.core.model.data.IAnswerData;
import org.javarosa.core.model.data.StringData;
import org.javarosa.form.api.FormEntryPrompt;
import org.odk.collect.android.R;
import org.odk.collect.android.activities.FormEntryActivity;
import org.odk.collect.android.application.Collect;
import org.odk.collect.android.utilities.FileUtils;
import org.odk.collect.android.utilities.MediaUtils;
import org.odk.collect.android.views.ButtonBuilder;

import java.io.File;

/**
 * Widget that allows user to take pictures, sounds or video and add them to the form.
 *
 * @author Carl Hartung (carlhartung@gmail.com)
 * @author Yaw Anokwa (yanokwa@gmail.com)
 */

public class AudioWidget extends QuestionWidget implements IBinaryWidget {
  private final static String t = "MediaWidget";

  private Button mCaptureButton;
  private Button mPlayButton;
  private Button mChooseButton;

  private String mBinaryName;
  private String mInstanceFolder;

  public AudioWidget(Context context, FormEntryPrompt prompt) {
    super(context, prompt);

    mInstanceFolder = Collect.getInstance().getFormController()
        .getInstancePath().getParent();

    setOrientation(LinearLayout.VERTICAL);

    TableLayout.LayoutParams params = new TableLayout.LayoutParams();
    params.setMargins(7, 5, 7, 5);

    // setup capture button
    final ButtonBuilder captureButtonBuilder = new ButtonBuilder(context);
    captureButtonBuilder.withParent(this);
    captureButtonBuilder.readOnly(prompt.isReadOnly());
    mCaptureButton = captureButtonBuilder.buildCaptureAudioButton();
    mCaptureButton.setLayoutParams(params);

    // launch capture intent on click
    mCaptureButton.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
        Collect.getInstance()
            .getActivityLogger()
            .logInstanceAction(this, "captureButton", "click",
                mPrompt.getIndex());
        Intent i = new Intent(
            android.provider.MediaStore.Audio.Media.RECORD_SOUND_ACTION);
        i.putExtra(
            android.provider.MediaStore.EXTRA_OUTPUT,
            android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
                .toString());
        try {
          Collect.getInstance().getFormController()
              .setIndexWaitingForData(mPrompt.getIndex());
          ((Activity) getContext()).startActivityForResult(i,
              FormEntryActivity.AUDIO_CAPTURE);
        } catch (ActivityNotFoundException e) {
          Toast.makeText(
              getContext(),
              getContext().getString(R.string.activity_not_found,
                  "audio capture"), Toast.LENGTH_SHORT)
              .show();
          Collect.getInstance().getFormController()
              .setIndexWaitingForData(null);
        }

      }
    });

    // setup capture button
    final ButtonBuilder chooseButtonBuilder = new ButtonBuilder(context);
    chooseButtonBuilder.readOnly(prompt.isReadOnly());
    chooseButtonBuilder.withParent(this);
    mChooseButton = chooseButtonBuilder.build();
    mChooseButton.setLayoutParams(params);

    // launch capture intent on click
    mChooseButton.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
        Collect.getInstance()
            .getActivityLogger()
            .logInstanceAction(this, "chooseButton", "click",
                mPrompt.getIndex());
        Intent i = new Intent(Intent.ACTION_GET_CONTENT);
        i.setType("audio/*");
        try {
          Collect.getInstance().getFormController()
              .setIndexWaitingForData(mPrompt.getIndex());
          ((Activity) getContext()).startActivityForResult(i,
              FormEntryActivity.AUDIO_CHOOSER);
        } catch (ActivityNotFoundException e) {
          Toast.makeText(
              getContext(),
              getContext().getString(R.string.activity_not_found,
                  "choose audio"), Toast.LENGTH_SHORT).show();
          Collect.getInstance().getFormController()
              .setIndexWaitingForData(null);
        }

      }
    });

    // setup play button
    final ButtonBuilder playButtonBuilder = new ButtonBuilder(context);
    playButtonBuilder.withTextResource(R.string.play_audio);
    playButtonBuilder.readOnly(prompt.isReadOnly());
    playButtonBuilder.withParent(this);
    mPlayButton = playButtonBuilder.build();
    mPlayButton.setLayoutParams(params);

    // on play, launch the appropriate viewer
    mPlayButton.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
        Collect.getInstance()
            .getActivityLogger()
            .logInstanceAction(this, "playButton", "click",
                mPrompt.getIndex());
        Intent i = new Intent("android.intent.action.VIEW");
        File f = new File(mInstanceFolder + File.separator
            + mBinaryName);
        i.setDataAndType(Uri.fromFile(f), "audio/*");
        try {
          ((Activity) getContext()).startActivity(i);
        } catch (ActivityNotFoundException e) {
          Toast.makeText(
              getContext(),
              getContext().getString(R.string.activity_not_found,
                  "play audio"), Toast.LENGTH_SHORT).show();
        }

      }
    });

    // retrieve answer from data model and update ui
    mBinaryName = prompt.getAnswerText();
    if (mBinaryName != null) {
      mPlayButton.setEnabled(true);
    } else {
      mPlayButton.setEnabled(false);
    }

    // finish complex layout
    addView(mCaptureButton);
    addView(mChooseButton);
    addView(mPlayButton);

    // and hide the capture and choose button if read-only
    if (mPrompt.isReadOnly()) {
      mCaptureButton.setVisibility(View.GONE);
      mChooseButton.setVisibility(View.GONE);
    }
  }


  private void deleteMedia() {
    // get the file path and delete the file
    String name = mBinaryName;
    // clean up variables
    mBinaryName = null;
    // delete from media provider
    int del = MediaUtils.deleteAudioFileFromMediaProvider(mInstanceFolder + File.separator + name);
    Log.i(t, "Deleted " + del + " rows from media content provider");
  }

  @Override
  public void clearAnswer() {
    // remove the file
    deleteMedia();

    // reset buttons
    mPlayButton.setEnabled(false);
  }

  @Override
  public IAnswerData getAnswer() {
    if (mBinaryName != null) {
      return new StringData(mBinaryName.toString());
    } else {
      return null;
    }
  }

  @Override
  public void setBinaryData(Object binaryuri) {
    // when replacing an answer. remove the current media.
    if (mBinaryName != null) {
      deleteMedia();
    }

    // get the file path and create a copy in the instance folder
    String binaryPath = MediaUtils.getPathFromUri(this.getContext(), (Uri) binaryuri, Audio.Media.DATA);
    String extension = binaryPath.substring(binaryPath.lastIndexOf("."));
    String destAudioPath = mInstanceFolder + File.separator
        + System.currentTimeMillis() + extension;

    File source = new File(binaryPath);
    File newAudio = new File(destAudioPath);
    FileUtils.copyFile(source, newAudio);

    if (newAudio.exists()) {
      // Add the copy to the content provier
      ContentValues values = new ContentValues(6);
      values.put(Audio.Media.TITLE, newAudio.getName());
      values.put(Audio.Media.DISPLAY_NAME, newAudio.getName());
      values.put(Audio.Media.DATE_ADDED, System.currentTimeMillis());
      values.put(Audio.Media.DATA, newAudio.getAbsolutePath());

      Uri AudioURI = getContext().getContentResolver().insert(
          Audio.Media.EXTERNAL_CONTENT_URI, values);
      Log.i(t, "Inserting AUDIO returned uri = " + AudioURI.toString());
      mBinaryName = newAudio.getName();
      Log.i(t, "Setting current answer to " + newAudio.getName());
    } else {
      Log.e(t, "Inserting Audio file FAILED");
    }

    Collect.getInstance().getFormController().setIndexWaitingForData(null);
  }

  @Override
  public void setFocus(Context context) {
    // Hide the soft keyboard if it's showing.
    InputMethodManager inputManager = (InputMethodManager) context
        .getSystemService(Context.INPUT_METHOD_SERVICE);
    inputManager.hideSoftInputFromWindow(this.getWindowToken(), 0);
  }

  @Override
  public boolean isWaitingForBinaryData() {
    return mPrompt.getIndex().equals(
        Collect.getInstance().getFormController()
            .getIndexWaitingForData());
  }

  @Override
  public void cancelWaitingForBinaryData() {
    Collect.getInstance().getFormController().setIndexWaitingForData(null);
  }

  @Override
  public void setOnLongClickListener(OnLongClickListener l) {
    mCaptureButton.setOnLongClickListener(l);
    mChooseButton.setOnLongClickListener(l);
    mPlayButton.setOnLongClickListener(l);
  }

  @Override
  public void cancelLongPress() {
    super.cancelLongPress();
    mCaptureButton.cancelLongPress();
    mChooseButton.cancelLongPress();
    mPlayButton.cancelLongPress();
  }

}
