package com.hapramp.ui.activity;

import android.Manifest;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.provider.MediaStore;
import android.support.annotation.NonNull;
import android.support.design.widget.Snackbar;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.FileProvider;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;

import com.google.gson.Gson;
import com.hapramp.R;
import com.hapramp.analytics.AnalyticsParams;
import com.hapramp.analytics.AnalyticsUtil;
import com.hapramp.analytics.EventReporter;
import com.hapramp.draft.DraftsHelper;
import com.hapramp.draft.ShortPostDraftModel;
import com.hapramp.preferences.HaprampPreferenceManager;
import com.hapramp.steem.PermlinkGenerator;
import com.hapramp.steem.SteemPostCreator;
import com.hapramp.utils.ConnectionUtils;
import com.hapramp.utils.Constants;
import com.hapramp.utils.GoogleImageFilePathReader;
import com.hapramp.utils.HashTagUtils;
import com.hapramp.utils.MomentsUtils;
import com.hapramp.utils.PostHashTagPreprocessor;
import com.hapramp.views.post.PostCreateComponent;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;

import butterknife.BindView;
import butterknife.ButterKnife;

public class CreatePostActivity extends AppCompatActivity implements SteemPostCreator.SteemPostCreatorCallback, DraftsHelper.DraftsHelperCallback {
  public static final String EXTRA_KEY_DRAFT_ID = "draftId";
  public static final String EXTRA_KEY_DRAFT_JSON = "draftJson";
  private static final int REQUEST_IMAGE_SELECTOR = 101;
  private static final int REQUEST_CAPTURE_IMAGE = 100;
  private final long NO_DRAFT = -1;
  @BindView(R.id.backBtn)
  ImageView closeBtn;
  @BindView(R.id.postButton)
  TextView postButton;
  @BindView(R.id.toolbar_container)
  RelativeLayout toolbarContainer;
  @BindView(R.id.post_create_component)
  PostCreateComponent postCreateComponent;
  @BindView(R.id.scroll_view)
  ScrollView scrollView;
  private ProgressDialog progressDialog;
  private List<String> tags;
  private String generated_permalink;
  private SteemPostCreator steemPostCreator;
  private List<String> images;
  private String body;
  private String cameraImageFilePath;
  private long mDraftId = NO_DRAFT;
  private boolean postPublished;
  private DraftsHelper draftsHelper;
  private boolean leftActivityWithPurpose = false;
  private boolean shouldSaveOrUpdateDraft = true;
  private String title;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_new_post_creation);
    ButterKnife.bind(this);
    init();
    initProgressDialog();
    attachListener();
    EventReporter.addEvent(AnalyticsParams.EVENT_OPENS_POST_CREATE);
  }

  private void init() {
    draftsHelper = new DraftsHelper();
    draftsHelper.setDraftsHelperCallback(this);
    getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
    steemPostCreator = new SteemPostCreator();
    steemPostCreator.setSteemPostCreatorCallback(this);
    Intent intent = getIntent();
    String action = intent.getAction();
    String type = intent.getType();
    if (Intent.ACTION_SEND.equals(action) && type != null) {
      if ("text/plain".equals(type)) {
        handleSendText(intent);
      } else if (type.startsWith("image/")) {
        handleSendImage(intent);
      }
    }

    Intent receiveIntent = getIntent();
    if (receiveIntent != null) {
      mDraftId = receiveIntent.getLongExtra(EXTRA_KEY_DRAFT_ID, NO_DRAFT);
      if (mDraftId != NO_DRAFT) {
        String draftJson = receiveIntent.getStringExtra(EXTRA_KEY_DRAFT_JSON);
        try {
          ShortPostDraftModel draftModel = new Gson().fromJson(draftJson, ShortPostDraftModel.class);
          configureEditor(draftModel);
        }
        catch (Exception e) {
          e.printStackTrace();
          configureEditor(null);
        }
      }
    } else {
      configureEditor(null);
    }
  }

  private void initProgressDialog() {
    progressDialog = new ProgressDialog(this);
    progressDialog.setIndeterminate(true);
    progressDialog.setCancelable(false);
    progressDialog.setMessage("Publishing...");
  }

  private void attachListener() {
    closeBtn.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
        showExistAlert();
      }
    });
    postButton.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
        publishPost();
      }
    });
    postCreateComponent.setMediaSelectorListener(new PostCreateComponent.MediaSelectorListener() {
      @Override
      public void onImageInsertOptionSelected() {
        openGallery();
      }

      @Override
      public void onCameraImageSelected() {
        checkCameraPermission();
      }
    });
  }

  private void handleSendText(Intent intent) {
    String sharedText = intent.getStringExtra(Intent.EXTRA_TEXT);
    postCreateComponent.setDefaultText(sharedText);
  }

  private void handleSendImage(Intent intent) {
    try {
      Uri imageUri = intent.getParcelableExtra(Intent.EXTRA_STREAM);
      intent.setData(imageUri);
      handleImageResult(intent);
    }
    catch (Exception e) {
      e.printStackTrace();
      Toast.makeText(this, "Something went wrong!", Toast.LENGTH_LONG).show();
    }
  }

  private void configureEditor(ShortPostDraftModel draftModel) {
    if (draftModel != null) {
      loadShortPostDraftIntoEditor(draftModel);
    }
  }

  private void showExistAlert() {
    if (!isValidDraftToSave()) {
      close();
      return;
    }
    //if there is already draft, show a progress with saving...
    if (mDraftId != NO_DRAFT) {
      showPublishingProgressDialog(true, "Saving changes...");
      shouldSaveOrUpdateDraft = false;
      updateDraft();
      return;
    }

    AlertDialog.Builder builder = new AlertDialog.Builder(this)
      .setTitle("Save as draft?")
      .setMessage("You can edit and publish saved drafts later.")
      .setPositiveButton("Save Draft", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
          //save or update draft
          shouldSaveOrUpdateDraft = true;
          close();
        }
      })
      .setNegativeButton("Discard", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialogInterface, int i) {
          // in delete mode
          shouldSaveOrUpdateDraft = false;
          close();
        }
      });
    builder.show();
  }

  private void publishPost() {
    if (!ConnectionUtils.isConnected(this)) {
      showConnectivityError();
      return;
    }
    if (validPost()) {
      showPublishingProgressDialog(true, "Preparing Your Post...");
      preparePost();
      showPublishingProgressDialog(true, "Pre-processing...");
      sendPostToSteemBlockChain();
    }
  }

  private void openGallery() {
    leftActivityWithPurpose = true;
    try {
      if (ActivityCompat.checkSelfPermission(CreatePostActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED
        ||
        ActivityCompat.checkSelfPermission(CreatePostActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(CreatePostActivity.this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_IMAGE_SELECTOR);
      } else {
        Intent intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
        intent.setType("image/*");
        startActivityForResult(intent, REQUEST_IMAGE_SELECTOR);
      }
    }
    catch (Exception e) {
      e.printStackTrace();
    }
  }

  private void checkCameraPermission() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
      try {
        if (ActivityCompat.checkSelfPermission(CreatePostActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED
          ||
          ActivityCompat.checkSelfPermission(CreatePostActivity.this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
          ActivityCompat.requestPermissions(CreatePostActivity.this, new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CAPTURE_IMAGE);
        } else {
          openCameraIntent();
        }
      }
      catch (Exception e) {
        e.printStackTrace();
      }
    } else {
      openCameraIntent();
    }
  }

  private void handleImageResult(final Intent intent) {
    final Handler handler = new Handler();
    new Thread() {
      @Override
      public void run() {
        final String filePath = GoogleImageFilePathReader.getImageFilePath(CreatePostActivity.this, intent);
        handler.post(new Runnable() {
          @Override
          public void run() {
            if (filePath != null) {
              addImage(filePath);
            } else {
              Toast.makeText(CreatePostActivity.this, "Failed to read shared image", Toast.LENGTH_LONG).show();
            }
          }
        });
      }
    }.start();
  }

  public void loadShortPostDraftIntoEditor(ShortPostDraftModel draft) {
    //set image
    String imageUrl = draft.getPostImageUrl();
    if (imageUrl != null) {
      if (imageUrl.length() > 0) {
        postCreateComponent.setImageDownloadUrl(imageUrl);
      }
    }
    //set title
    postCreateComponent.setTitle(draft.getTitle());
    //set text
    postCreateComponent.setDefaultText(draft.getText());
    //set community
    postCreateComponent.setDefaultCommunitySelection(draft.getCommunities());
  }

  private boolean isValidDraftToSave() {
    return postCreateComponent.getImageList().size() > 0 || postCreateComponent.getContent().length() > 0;
  }

  private void close() {
    closeCreatePostPage();
    overridePendingTransition(R.anim.slide_down_enter, R.anim.slide_down_exit);
  }

  private void showPublishingProgressDialog(boolean show, String msg) {
    if (progressDialog != null) {
      if (show) {
        progressDialog.setMessage(msg);
        progressDialog.setIndeterminate(true);
        progressDialog.show();
      } else {
        progressDialog.dismiss();
      }
    } else {
      progressDialog.dismiss();
    }
  }

  private void updateDraft() {
    ShortPostDraftModel shortPostDraftModel = new ShortPostDraftModel();
    if (postCreateComponent.getImageList().size() > 0) {
      shortPostDraftModel.setPostImageUrl(postCreateComponent.getImageList().get(0));
    }
    if (postCreateComponent.getBody().length() > 0) {
      shortPostDraftModel.setText(postCreateComponent.getContent());
    }
    shortPostDraftModel.setCommunities(postCreateComponent.getSelectedCommunityTags());
    String draftTitle = postCreateComponent.getTitle();
    shortPostDraftModel.setTitle(draftTitle);
    shortPostDraftModel.setDraftId(mDraftId);
    draftsHelper.updateShortPostDraft(shortPostDraftModel);
  }

  private void showConnectivityError() {
    Snackbar.make(toolbarContainer, "No Internet!", Snackbar.LENGTH_SHORT).show();
  }

  private boolean validPost() {
    if (postCreateComponent.getSelectedCommunityTags().size() > 1) {
      if (postCreateComponent.isMediaSelected()) {
        if (postCreateComponent.isMediaUploaded()) {
          return true;
        } else {
          toast("Please wait until the upload is complete...");
          return false;
        }
      } else {
        if (postCreateComponent.isContentEnough()) {
          return true;
        } else {
          toast("Write something more...");
        }
      }
    } else {
      toast("Select atleast 1 community");
    }
    return false;
  }

  private void preparePost() {
    generated_permalink = PermlinkGenerator.getPermlink();
    title = postCreateComponent.getTitle();
    body = postCreateComponent.getBody();
    body = body + Constants.FOOTER_TEXT;
    tags = postCreateComponent.getSelectedCommunityTags();
    tags.addAll(getHashTagsFromBody(body));
    tags = PostHashTagPreprocessor.processHashtags(tags);
    body = HashTagUtils.cleanHashTagsFromBody(body);
    images = postCreateComponent.getImageList();
  }

  private void sendPostToSteemBlockChain() {
    showPublishingProgressDialog(true, "Publishing...");
    steemPostCreator.createPost(body, title, images, tags, generated_permalink);
  }

  private void openCameraIntent() {
    leftActivityWithPurpose = true;
    Intent pictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    if (pictureIntent.resolveActivity(getPackageManager()) != null) {
      File photoFile = null;
      try {
        photoFile = createImageFile();
      }
      catch (IOException ex) {

      }
      if (photoFile != null) {
        Uri photoURI = FileProvider.getUriForFile(this, "com.hapramp.provider", photoFile);
        pictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,
          photoURI);
        startActivityForResult(pictureIntent,
          REQUEST_CAPTURE_IMAGE);
      }
    }
  }

  private void addImage(String filePath) {
    postCreateComponent.setImageResource(filePath);
  }

  private void closeCreatePostPage() {
    finish();
  }

  private void toast(String s) {
    Toast.makeText(this, s, Toast.LENGTH_LONG).show();
  }

  private ArrayList<String> getHashTagsFromBody(String body) {
    return HashTagUtils.getHashTags(body);
  }

  private File createImageFile() throws IOException {
    String timeStamp =
      new SimpleDateFormat("yyyyMMdd_HHmmss",
        Locale.getDefault()).format(new Date());
    String imageFileName = "IMG_" + timeStamp + "_";
    File storageDir =
      getExternalFilesDir(Environment.DIRECTORY_PICTURES);
    File image = File.createTempFile(
      imageFileName,  /* prefix */
      ".jpg",         /* suffix */
      storageDir      /* directory */
    );
    cameraImageFilePath = image.getAbsolutePath();
    return image;
  }

  @Override
  protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == REQUEST_IMAGE_SELECTOR && resultCode == Activity.RESULT_OK && data != null && data.getData() != null) {
      leftActivityWithPurpose = false;
      handleImageResult(data);
    }

    if (requestCode == REQUEST_CAPTURE_IMAGE && resultCode == RESULT_OK) {
      leftActivityWithPurpose = false;
      addImage(cameraImageFilePath);
    }
  }

  @Override
  public void onBackPressed() {
    showExistAlert();
  }

  @Override
  protected void onPause() {
    super.onPause();
    invalidateDraft();
  }

  @Override
  public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) {
    switch (requestCode) {
      case REQUEST_IMAGE_SELECTOR:
        // If request is cancelled, the result arrays are empty.
        if (grantResults.length > 0
          && grantResults[0] == PackageManager.PERMISSION_GRANTED
          && grantResults[1] == PackageManager.PERMISSION_GRANTED) {
          openGallery();
        } else {
          //do something like displaying a message that he didn`t allow the app to access gallery and you wont be able to let him select from gallery
          toast("Permission not granted to access images.");
        }
        break;
      case REQUEST_CAPTURE_IMAGE:
        // If request is cancelled, the result arrays are empty.
        if (grantResults.length > 0
          && grantResults[0] == PackageManager.PERMISSION_GRANTED
          && grantResults[1] == PackageManager.PERMISSION_GRANTED) {
          openCameraIntent();
        } else {
          //do something like displaying a message that he didn`t allow the app to access gallery and you wont be able to let him select from gallery
          toast("Permission not granted to capture images.");
        }
        break;
    }
  }

  private void invalidateDraft() {
    if (mDraftId != NO_DRAFT) {
      if (postPublished) {
        //delete draft
        deleteDraft();
      } else {
        //update draft
        if (!leftActivityWithPurpose) {
          if (shouldSaveOrUpdateDraft) {
            updateDraft();
          }
        }
      }
    } else {
      if (!postPublished && !leftActivityWithPurpose) {
        if (shouldSaveOrUpdateDraft) {
          //save draft
          addNewDraft();
        }
      }
    }
  }

  private void deleteDraft() {
    draftsHelper.deleteDraft(mDraftId);
  }

  private void addNewDraft() {
    if (!isValidDraftToSave()) {
      return;
    }
    ShortPostDraftModel shortPostDraftModel = new ShortPostDraftModel();
    if (postCreateComponent.getImageList().size() > 0) {
      shortPostDraftModel.setPostImageUrl(postCreateComponent.getImageList().get(0));
    }

    if (postCreateComponent.getContent().length() > 0) {
      shortPostDraftModel.setText(postCreateComponent.getContent());
    }
    shortPostDraftModel.setCommunities(postCreateComponent.getSelectedCommunityTags());
    String draftTitle = postCreateComponent.getTitle();
    shortPostDraftModel.setTitle(draftTitle);
    draftsHelper.saveShortPostDraft(shortPostDraftModel);
  }

  @Override
  public void onPostCreatedOnSteem() {
    toast("Published");
    postPublished = true;
    showPublishingProgressDialog(false, "");
    postCreated();
  }

  private void postCreated() {
    showPublishingProgressDialog(false, "");
    AnalyticsUtil.logEvent(AnalyticsParams.EVENT_CREATE_POST);
    HaprampPreferenceManager.getInstance().setLastPostCreatedAt(MomentsUtils.getCurrentTime());
    new Handler().postDelayed(new Runnable() {
      @Override
      public void run() {
        closeCreatePostPage();
      }
    }, 1000);
  }

  @Override
  public void onPostCreationFailedOnSteem(String msg) {
    toast("Cannot create post.");
    Log.d("PostCreate", msg);
    showPublishingProgressDialog(false, "");
  }

  @Override
  public void onNewDraftSaved(boolean success,int mDraftId) {
    this.mDraftId = mDraftId;
  }

  @Override
  public void onDraftUpdated(boolean success,int draftId) {
    this.mDraftId = draftId;
    showPublishingProgressDialog(false, "");
    close();
  }

  @Override
  public void onDraftDeleted(boolean success) {
  }
}