package jp.co.corecorp.s3pdf;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

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

import com.artifex.mupdf.MuPDFCore;
import com.artifex.mupdf.MuPDFPageAdapter;
import com.artifex.mupdf.MuPDFPageView;
import com.artifex.mupdf.PageView;
import com.artifex.mupdf.ReaderView;

import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.app.ActionBar;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.text.method.PasswordTransformationMethod;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.TranslateAnimation;
import android.view.inputmethod.EditorInfo;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.BaseAdapter;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;

public class PdfActivity extends Activity {
	ListAdapter	listAdapter = null;
	SharePDF cdata = null;
	private S3Resource  resource = null;
	private ImageView	mThumbIcon = null;
	private View 		mGadgetBase = null;
	private ListView	mGadgetList = null;

	/* The core rendering instance */
	private enum LinkState {DEFAULT, HIGHLIGHT, INHIBIT};
	private static final int TAP_PAGE_MARGIN = 5;
	private static final int REQUEST_GALLERY = 0;
	private static final int REQUEST_OUTLINE = 1;
	private MuPDFCore    core = null;
	private ReaderView   mDocView = null;
	private View         mButtonsView = null;
	private boolean      mButtonsVisible = false;
	private boolean      mListVisible = false;
	private EditText     mPasswordView = null;
	private SeekBar      mPageSlider = null;
	private TextView     mPageNumberView = null;
	private AlertDialog.Builder mAlertBuilder = null;

	private class ListAdapter extends GadgetAdapter {
		ListAdapter(SharePDF cdata) {
			super(cdata, SharePDF.RESOURCE_IMAGE_ATTACHTAG);
		}
		public View getView(int position, View view, ViewGroup parent) {
			if( view == null ) {
				view = inflater.inflate(R.layout.gadgetlist_row, null);
			}
			String imgTag = (String)getItem(position);
			if( imgTag == null ) return null;
			File imgFile;
			try {
				imgFile = rsc.findStreamGadetFile(imgTag);
			} catch (S3Exception e) {
				return null;
			} catch (S3TypeException e) {
				return null;
			}
			
			S3Context con = cdata.getS3Con();
			Context ctx = con.getContext();
			BitmapFactory.Options opt = new BitmapFactory.Options();
			opt.inJustDecodeBounds = true;
			BitmapFactory.decodeFile(imgFile.toString(), opt);
			
			final float density = ctx.getResources().getDisplayMetrics().density;  
			int imgSize = (int)(350 * density + 0.5f);
			int scaleW = opt.outWidth / imgSize + 1;
			int scaleH = opt.outHeight / imgSize + 1;
			int scale;
			if( scaleW > scaleH )
				scale = scaleW;
			else
				scale = scaleW;
			opt.inSampleSize = scale;
			opt.inJustDecodeBounds = false;
			Bitmap bmp = BitmapFactory.decodeFile(imgFile.toString(), opt);
			ImageView iv = (ImageView)view.findViewById(R.id.gadget_img);
			iv.setImageBitmap(bmp);

			String modText = "";
			S3Gadget g = rsc.findGadget(imgTag);
			if( g != null ) {
				Date modiTime = g.getLastModifyTime();
				if( modiTime != null ) {
					DateFormat df = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
					modText = df.format(modiTime);
				}
			}
			TextView tv = (TextView)view.findViewById(R.id.gadget_text);
			tv.setText(modText);
			
			return view;
		}
	}
	
	private MuPDFCore openFile(String path)
	{
		int lastSlashPos = path.lastIndexOf('/');
		System.out.println("Trying to open "+path);
		try
		{
			core = new MuPDFCore(path);
			// New file: drop the old outline data
			// OutlineActivityData.set(null);
		}
		catch (Exception e)
		{
			System.out.println(e);
			return null;
		}
		return core;
	}

	boolean isPortrait() {
		Configuration config = getResources().getConfiguration();
		if (config.orientation == Configuration.ORIENTATION_PORTRAIT) {
			return true;
		}
		return false;
	}
	
	boolean isLandscape() {
		Configuration config = getResources().getConfiguration();
		if(config.orientation == Configuration.ORIENTATION_LANDSCAPE) { 
			return true;
		}
		return false;
	}
	
	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
        cdata = (SharePDF)getApplication();
        if( cdata == null ) {
        	finish();
        	return;
        }
/*
		if (core == null) {
			core = (MuPDFCore)getLastNonConfigurationInstance();

			if (savedInstanceState != null && savedInstanceState.containsKey("FileName")) {
				mFileName = savedInstanceState.getString("FileName");
			}
		}
*/
		if (core == null) {
			Intent intent = getIntent();
			if (Intent.ACTION_VIEW.equals(intent.getAction())) {
				Uri uri = null;
				Bundle pm = intent.getExtras();
				String rsn = pm.getString("ResourceName");
				if( rsn != null ) {
					if( cdata == null ) {
						cdata = null;
					}
					S3Context con = cdata.getS3Con();
					S3ServiceManager sm = con.getServiceManager();
					S3Application svc = sm.findService(SharePDF.SharePdfService);
					resource = svc.findResource(rsn);
					if( resource != null ) {
						String path = null;
						try {
							path = resource.getDemoFilePath();
						}
						catch(S3Exception e) {
							Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG).show();
							return;
						}
						if( path != null ) {
							uri = Uri.parse(path);
						}
					}
				}
				if( uri == null )
					uri = intent.getData();
				
				if( uri != null ) {
					if (uri.toString().startsWith("content://media/external/file")) {
						// Handle view requests from the Transformer Prime's file manager
						// Hopefully other file managers will use this same scheme, if not
						// using explicit paths.
						Cursor cursor = getContentResolver().query(uri, new String[]{"_data"}, null, null, null);
						if (cursor.moveToFirst()) {
							uri = Uri.parse(cursor.getString(0));
						}
					}
					core = openFile(Uri.decode(uri.getEncodedPath()));
				}
			}
			
			if (core != null && core.needsPassword()) {
				requestPassword(savedInstanceState);
				return;
			}
			
		}
		
		/*
		if (core == null)
		{
			mAlertBuilder = new AlertDialog.Builder(this);
			AlertDialog alert = mAlertBuilder.create();
			alert.setTitle(R.string.open_failed);
			alert.setButton(AlertDialog.BUTTON_POSITIVE, "Dismiss",
					new DialogInterface.OnClickListener() {
						public void onClick(DialogInterface dialog, int which) {
							finish();
						}
					});
			alert.show();
			return;
		}
		*/
		createUI(savedInstanceState);
	}

	public void onStart() {
		super.onStart();
		ActionBar actionBar = this.getActionBar();
		actionBar.setDisplayHomeAsUpEnabled(true);
	}
	public void requestPassword(final Bundle savedInstanceState) {
		mPasswordView = new EditText(this);
		mPasswordView.setInputType(EditorInfo.TYPE_TEXT_VARIATION_PASSWORD);
		mPasswordView.setTransformationMethod(new PasswordTransformationMethod());

		AlertDialog alert = mAlertBuilder.create();
		alert.setTitle(R.string.enter_password);
		alert.setView(mPasswordView);
		alert.setButton(AlertDialog.BUTTON_POSITIVE, "Ok",
				new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface dialog, int which) {
				if (core.authenticatePassword(mPasswordView.getText().toString())) {
					createUI(savedInstanceState);
				} else {
					requestPassword(savedInstanceState);
				}
			}
		});
		alert.setButton(AlertDialog.BUTTON_NEGATIVE, "Cancel",
				new DialogInterface.OnClickListener() {

			public void onClick(DialogInterface dialog, int which) {
				finish();
			}
		});
		alert.show();
	}
	
	private OnItemLongClickListener onItemLongClick = new OnItemLongClickListener() {
		public boolean onItemLongClick(AdapterView<?> parent, View view,
				int position, long id) {
			String imgTag = (String)listAdapter.getItem(position);
			try {
				resource.removeGadget(imgTag);
				resource.removeTag(SharePDF.RESOURCE_IMAGE_ATTACHTAG);
			} catch (S3Exception e) {
			} catch (S3TypeException e) {
			}
			listAdapter.notifyDataSetChanged();
			return true;
		}
	};
	
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_pdf, menu);
        return true;
    }
    
	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		if( item.getItemId() == android.R.id.home) {
			finish();
            return true;
		}
		if( item.getItemId() == R.id.menu_card_edit) {
    		Intent intent = new Intent(PdfActivity.this.cdata,CardActivity.class);
    		intent.setAction(Intent.ACTION_VIEW);
			if( resource != null ) {
	    		intent.putExtra("ResourceName", resource.getResourceName());
	    		startActivity(intent);
			}
            return true;
		}
		if( item.getItemId() == R.id.menu_photo_add) {
			Intent intent = new Intent();
			intent.setType("image/*");
			intent.setAction(Intent.ACTION_GET_CONTENT);
			startActivityForResult(intent, REQUEST_GALLERY);		
            return true;
		}
		return super.onOptionsItemSelected(item);
	}

	private void createUI(Bundle savedInstanceState) {
		if( isLandscape() ) { 
			createLandscapeUI(savedInstanceState);
		} else {
			createPortraitUI(savedInstanceState);
		}
		ListView listView = (ListView)findViewById(R.id.gadgetlist);
        cdata = (SharePDF)getApplication();

	    listAdapter	= new ListAdapter(cdata);
		listAdapter.setResource(resource);
	    listView.setAdapter(listAdapter);		
	    listView.setOnItemLongClickListener(onItemLongClick);
/*	    
	    ImageView iv = (ImageView)findViewById(R.id.syncIcon);
	    AnimationDrawable ad =(AnimationDrawable) getResources().getDrawable(android.R.drawable.ic_popup_sync);
	    iv.setImageDrawable(ad);
	    ad.start();
*/
	    /*
		listView = (ListView)findViewById(R.id.statusBar);
	    adapter2 = new ArrayAdapter<String>(
	    	      this, 
	    	      android.R.layout.simple_list_item_1, 
	    	      dataList);
	    listView.setAdapter(adapter2);		
	    adapter2.add("test1");
	    adapter2.add("test2");
	    adapter2.add("test3");
	    */
	}
	
	public void createPortraitUI(Bundle savedInstanceState) {
		LayoutInflater inflater = getLayoutInflater();
		ViewGroup viewLayout = (ViewGroup)inflater.inflate(R.layout.activity_pdf, null);
		setContentView(viewLayout);

		mGadgetList	= (ListView)findViewById(R.id.gadgetlist);
		mGadgetBase	= findViewById(R.id.floatView);
		mThumbIcon	= (ImageView)findViewById(R.id.thumbIcon);
		mThumbIcon.setOnClickListener(onThumbClick);

//		ListView listView = (ListView)findViewById(R.id.gadgetlist);
//		RelativeLayout.LayoutParams llp = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
//		listView.setLayoutParams(llp);
		
		RelativeLayout layout = null;
		if (core != null) {
			layout = createPDFView(savedInstanceState);
			viewLayout.addView(layout,0);
			//FrameLayout frame = (FrameLayout)findViewById(R.id.floatView);
			//frame.addView(layout,0);
			if( mListVisible )
				showLists(true);
			else
				hideLists(true);
		} else {
			showLists(true);
		}
	}

	public void createLandscapeUI(Bundle savedInstanceState) {
		LayoutInflater inflater = getLayoutInflater();
		ViewGroup viewLayout = (ViewGroup)inflater.inflate(R.layout.activity_pdf, null);
		setContentView(viewLayout);
		
		mGadgetList	= (ListView)findViewById(R.id.gadgetlist);
		mGadgetBase	= findViewById(R.id.floatView);
		mThumbIcon	= (ImageView)findViewById(R.id.thumbIcon);
		mThumbIcon.setOnClickListener(onThumbClick);
		
		RelativeLayout layout = null;
		if (core != null) {
			layout = createPDFView(savedInstanceState);
			viewLayout.addView(layout,0);
			//FrameLayout frame = (FrameLayout)findViewById(R.id.floatView);
			//frame.addView(layout,0);
			if( mListVisible )
				showLists(true);
			else
				hideLists(true);
		} else {
			showLists(true);
		}
	}
	
	RelativeLayout createPDFView(Bundle savedInstanceState) {
		mDocView = new ReaderView(this) {
			private boolean showButtonsDisabled;

			public boolean onSingleTapUp(MotionEvent e) {
				if (e.getX() < super.getWidth()/TAP_PAGE_MARGIN) {
					super.moveToPrevious();
				} else if (e.getX() > super.getWidth()*(TAP_PAGE_MARGIN-1)/TAP_PAGE_MARGIN) {
					super.moveToNext();
				} else if (!showButtonsDisabled) {
					if (!mButtonsVisible) {
						showButtons();
					} else {
						hideButtons();
					}
				}
				return super.onSingleTapUp(e);
			}

			public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
				if (!showButtonsDisabled)
					hideButtons();

				return super.onScroll(e1, e2, distanceX, distanceY);
			}

			public boolean onScaleBegin(ScaleGestureDetector d) {
				// Disabled showing the buttons until next touch.
				// Not sure why this is needed, but without it
				// pinch zoom can make the buttons appear
				showButtonsDisabled = true;
				return super.onScaleBegin(d);
			}

			public boolean onTouchEvent(MotionEvent event) {
				if (event.getActionMasked() == MotionEvent.ACTION_DOWN)
					showButtonsDisabled = false;

				return super.onTouchEvent(event);
			}

			protected void onMoveToChild(int i) {
				if (core == null)
					return;
				mPageNumberView.setText(String.format("%d/%d", i+1, core.countPages()));
				mPageSlider.setMax(core.countPages()-1);
				mPageSlider.setProgress(i);
			}

			protected void onSettle(View v) {
				// When the layout has settled ask the page to render
				// in HQ
				((PageView)v).addHq();
			}

			protected void onUnsettle(View v) {
				// When something changes making the previous settled view
				// no longer appropriate, tell the page to remove HQ
				((PageView)v).removeHq();
			}
		};
		Log.d("PdfActivity", "new ReaderView");
		
		mDocView.setAdapter(new MuPDFPageAdapter(this, core));
		Log.d("PdfActivity", "setAdapter");
		makeButtonsView();
		mPageSlider.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
			public void onStopTrackingTouch(SeekBar seekBar) {
				mDocView.setDisplayedViewIndex(seekBar.getProgress());
			}

			public void onStartTrackingTouch(SeekBar seekBar) {}

			public void onProgressChanged(SeekBar seekBar, int progress,
					boolean fromUser) {
				updatePageNumView(progress);
			}
		});

		// Reenstate last state if it was recorded
		SharedPreferences prefs = getPreferences(Context.MODE_PRIVATE);
		mDocView.setDisplayedViewIndex(0);
		Log.d("PdfActivity", "setDisplayedViewIndex");

		if (savedInstanceState == null || !savedInstanceState.getBoolean("ButtonsHidden", false))
			showButtons();

		// Stick the document view and the buttons overlay into a parent view
		RelativeLayout layout = new RelativeLayout(this);
		layout.addView(mDocView);
		layout.addView(mButtonsView);
		layout.setBackgroundResource(R.drawable.tiled_background);
		Log.d("PdfActivity", "addView");
		
		return layout;
	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		if( requestCode == REQUEST_GALLERY && resultCode == RESULT_OK ) {
			Uri uri = data.getData();
			InputStream in = null;
			try {
				in = getContentResolver().openInputStream(uri);
			} catch (FileNotFoundException e1) {
				return;
			}
			
			String imgTag = resource.createUniqueId();
			try {
				resource.setGadget(imgTag, in);
				resource.setGadgetTag(imgTag, SharePDF.RESOURCE_IMAGE_ATTACHTAG);
				resource.setTag(SharePDF.RESOURCE_IMAGE_ATTACHTAG);
			} catch (S3Exception e1) {
				return;
			} catch (S3TypeException e) {
				e.printStackTrace();
				return;
			}
			if( !mListVisible ) {
				showLists(false);
			}
			listAdapter.notifyDataSetChanged();
		}
		if( requestCode == REQUEST_OUTLINE && resultCode >= 0 ) {
			mDocView.setDisplayedViewIndex(resultCode);
		}
		super.onActivityResult(requestCode, resultCode, data);
	}

	public Object onRetainNonConfigurationInstance()
	{
		MuPDFCore mycore = core;
		core = null;
		return mycore;
	}

	@Override
	protected void onSaveInstanceState(Bundle outState) {
		super.onSaveInstanceState(outState);

		if (resource != null && mDocView != null) {
			SharedPreferences prefs = getPreferences(Context.MODE_PRIVATE);
			SharedPreferences.Editor edit = prefs.edit();
			edit.putInt("page"+resource.getResourceName(), mDocView.getDisplayedViewIndex());
			edit.commit();
		}

		if (!mButtonsVisible)
			outState.putBoolean("ButtonsHidden", true);
	}

	@Override
	protected void onPause() {
		super.onPause();
		if (resource != null && mDocView != null) {
			SharedPreferences prefs = getPreferences(Context.MODE_PRIVATE);
			SharedPreferences.Editor edit = prefs.edit();
			edit.putInt("page"+resource.getResourceName(), mDocView.getDisplayedViewIndex());
			edit.commit();
		}
	}

	@Override
	protected void onResume() {
		Log.d("PdfActivity", "onResume");
		if( listAdapter != null )
			listAdapter.notifyDataSetChanged();
		super.onResume();
	}

	public void onDestroy()
	{
		if (core != null)
			core.onDestroy();
		core = null;
		super.onDestroy();
	}

    private View.OnClickListener onThumbClick = new View.OnClickListener() {
    	public void onClick(View v) {
    		if( mListVisible )
    			PdfActivity.this.hideLists(false);
    		else
    			PdfActivity.this.showLists(false);
    	}
   	};
   	
	void showLists(boolean quick) {
		mListVisible	= true;
		//if( quick ) {
			mGadgetList.setVisibility(View.VISIBLE);
			mThumbIcon.setImageResource(R.drawable.ic_arrow_close);
			return;
		//}
		/*
		Animation anim = new TranslateAnimation(-mThumbIcon.getX(), 0, mGadgetBase.getY(), mGadgetBase.getY());
		anim.setDuration(300);
		anim.setAnimationListener(new Animation.AnimationListener() {
			public void onAnimationStart(Animation animation) {
				mGadgetList.setVisibility(View.VISIBLE);
			}
			public void onAnimationRepeat(Animation animation) {}
			public void onAnimationEnd(Animation animation) {
				mGadgetBase.setAnimation(null);
				mThumbIcon.setImageResource(R.drawable.ic_arrow_close);
			}
		});
		mGadgetBase.startAnimation(anim);
		*/
	}
	
	void hideLists(boolean quick) {
		mListVisible	= false;
		if( quick ) {
			mGadgetList.setVisibility(View.GONE);
			mThumbIcon.setImageResource(R.drawable.ic_arrow_open);
			return;
		}
		Animation anim = new TranslateAnimation(0, -mThumbIcon.getX(), mGadgetBase.getY(), mGadgetBase.getY());
		anim.setDuration(300);
		anim.setAnimationListener(new Animation.AnimationListener() {
			public void onAnimationStart(Animation animation) { }
			public void onAnimationRepeat(Animation animation) {}
			public void onAnimationEnd(Animation animation) {
				mGadgetList.setVisibility(View.GONE);
				mGadgetBase.setAnimation(null);
				mThumbIcon.setImageResource(R.drawable.ic_arrow_open);
			}
		});
		mGadgetBase.startAnimation(anim);
	}
	
	void showButtons() {
		if (core == null)
			return;
		if (!mButtonsVisible) {
			mButtonsVisible = true;
			// Update page number text and slider
			int index = mDocView.getDisplayedViewIndex();
			updatePageNumView(index);
			mPageSlider.setMax(core.countPages()-1);
			mPageSlider.setProgress(index);

			Animation anim = new TranslateAnimation(0, 0, mPageSlider.getHeight(), 0);
			anim.setDuration(200);
			anim.setAnimationListener(new Animation.AnimationListener() {
				public void onAnimationStart(Animation animation) {
					mPageSlider.setVisibility(View.VISIBLE);
				}
				public void onAnimationRepeat(Animation animation) {}
				public void onAnimationEnd(Animation animation) {
					mPageNumberView.setVisibility(View.VISIBLE);
				}
			});
			mPageSlider.startAnimation(anim);
		}
	}

	void hideButtons() {
		if (mButtonsVisible) {
			mButtonsVisible = false;

			Animation anim = new TranslateAnimation(0, 0, 0, mPageSlider.getHeight());
			anim.setDuration(200);
			anim.setAnimationListener(new Animation.AnimationListener() {
				public void onAnimationStart(Animation animation) {
					mPageNumberView.setVisibility(View.INVISIBLE);
				}
				public void onAnimationRepeat(Animation animation) {}
				public void onAnimationEnd(Animation animation) {
					mPageSlider.setVisibility(View.INVISIBLE);
				}
			});
			mPageSlider.startAnimation(anim);
		}
	}

	void updatePageNumView(int index) {
		if (core == null)
			return;
		mPageNumberView.setText(String.format("%d/%d", index+1, core.countPages()));
	}

	void makeButtonsView() {
		mButtonsView = getLayoutInflater().inflate(R.layout.buttons,null);
		mPageSlider = (SeekBar)mButtonsView.findViewById(R.id.pageSlider);
		mPageNumberView = (TextView)mButtonsView.findViewById(R.id.pageNumber);
		mPageNumberView.setVisibility(View.INVISIBLE);
		mPageSlider.setVisibility(View.INVISIBLE);
	}
/*
	void showKeyboard() {
		InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
		if (imm != null)
			imm.showSoftInput(mSearchText, 0);
	}

	void hideKeyboard() {
		InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
		if (imm != null)
			imm.hideSoftInputFromWindow(mSearchText.getWindowToken(), 0);
	}
*/
}
