package com.duguang.baseanimation.ui.flip.issue5;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.WeakReference;
import java.net.URL;
import java.net.URLConnection;

import junit.framework.Assert;
import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.view.Display;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;

import com.aphidmobile.flip.FlipViewController;
import com.aphidmobile.utils.AphidLog;
import com.aphidmobile.utils.IO;
import com.duguang.baseanimation.R;

/**
 * Modified from the issue#5 comment contributed by @cagkanciloglu <p/> Only corrected its async
 * loading logic, although its layout hierarchy can be optimized too.
 */
public class GalleryFlipItem extends LinearLayout {

  /**
   * Borrowed from the official BitmapFun tutorial: http://developer.android.com/training/displaying-bitmaps/index.html
   */
  private static final class AsyncDrawable extends BitmapDrawable {

    private final WeakReference<ContentPhotosDownloader> taskRef;

    public AsyncDrawable(Resources res, Bitmap bitmap, ContentPhotosDownloader task) {
      super(res, bitmap);
      this.taskRef = new WeakReference<ContentPhotosDownloader>(task);
    }

    public static ContentPhotosDownloader getTask(ImageView imageView) {
      Drawable drawable = imageView.getDrawable();
      if (drawable instanceof AsyncDrawable) {
        return ((AsyncDrawable) drawable).taskRef.get();
      }

      return null;
    }
  }

  //Change to a static inner class from a normal inner class, otherwise it may holds a strong reference to GalleryFlipItem, which is not a good practise for AsyncTask 
  private static class ContentPhotosDownloader extends AsyncTask<Void, Void, Bitmap> {

    private String url;

    private WeakReference<FlipViewController> controllerRef;
    //Use WeakReference
    private WeakReference<ImageView> imgViewRef;
    private WeakReference<ProgressBar> progressBarRef;
    private int pageIndex;
    private boolean hideProgress;

    public ContentPhotosDownloader(String url, ImageView imgView, ProgressBar progressBar,
                                   FlipViewController controller, int pageIndex) {
      Assert.assertNotNull(url);
      Assert.assertNotNull(imgView);
      Assert.assertNotNull(controller);
      //progressBar can be null

      this.url = url;
      this.imgViewRef = new WeakReference<ImageView>(imgView);
      this.controllerRef = new WeakReference<FlipViewController>(controller);
      this.pageIndex = pageIndex;
      if (progressBar != null) {
        progressBarRef = new WeakReference<ProgressBar>(progressBar);
      }
    }

    public String getUrl() {
      return url;
    }

    public int getPageIndex() {
      return pageIndex;
    }

    private ProgressBar getProgressBar() {
      return progressBarRef != null ? progressBarRef.get() : null;
    }

    @Override
    protected void onPreExecute() {
      super.onPreExecute();

      ProgressBar bar = getProgressBar();
      if (bar != null) {
        bar.setVisibility(View.VISIBLE);
        ImageView iv = imgViewRef.get();
        if (iv != null) {
          iv.setVisibility(GONE);
        }
      }

      //Commented out; pd and imgBackground should not be accessed directly                         
      /*
        pd.setVisibility(View.VISIBLE);
        imgBackground.setVisibility(View.GONE);
	*/
    }

    @Override
    protected Bitmap doInBackground(Void... params) {
      InputStream is = null;
      try {
        URL aURL = new URL(url);
        URLConnection conn = aURL.openConnection();

        conn.connect();

        is = new BufferedInputStream(conn.getInputStream());

        return BitmapFactory.decodeStream(is);
      } catch (IOException e) {
        AphidLog.e(e, "Failed to load bitmap from url: " + url);
      } finally {
        IO.close(is);
      }

      return null;
    }

    @Override
    protected void onPostExecute(Bitmap result) {
      if (isCancelled()) {
        return;
      }

      ImageView imgView = imgViewRef.get();

      if (imgView != null && AsyncDrawable.getTask(imgView)
                             == this) { //make sure the ImageView instance has not been reused for another page
        if (result != null) {
          imgView.setImageBitmap(result);
          imgView.setVisibility(View.VISIBLE);
        }

        ProgressBar bar = getProgressBar();
        if (bar != null) {
          bar.setVisibility(View.GONE);
        }

        FlipViewController controller = controllerRef.get();
        if (controller != null) {
          controller.refreshPage(pageIndex);
        }
      }
    }
  }

  public GalleryPage mGalleryPage;

  private ImageView imgBackground;
  private ProgressBar pd;
  private LinearLayout lnlPlace;

  private ImageView imgIcon;
  private TextView txtName;
  private TextView txtDistrict;
  private TextView txtCity;

  private Context mContext;

  public void refreshView(GalleryPage mGalleryPage, FlipViewController controller, int pageIndex) {
    this.mGalleryPage = mGalleryPage;

    if (shouldStartAsyncLoad(imgIcon, mGalleryPage.getTargetURL(), pageIndex)) {
      ContentPhotosDownloader
          downloader =
          new ContentPhotosDownloader(mGalleryPage.getTargetURL(), imgIcon, null, controller,
                                      pageIndex);
      imgIcon.setImageDrawable(new AsyncDrawable(getResources(), null, downloader));
      downloader.execute();
    }

    txtName.setText(this.mGalleryPage.getPageTitle());

    if (shouldStartAsyncLoad(imgBackground, mGalleryPage.getImageURL(), pageIndex)) {
      ContentPhotosDownloader
          downloader =
          new ContentPhotosDownloader(mGalleryPage.getImageURL(), imgBackground, pd, controller,
                                      pageIndex);
      imgBackground.setImageDrawable(new AsyncDrawable(getResources(), null, downloader));
      downloader.execute();
    }
  }

  private boolean shouldStartAsyncLoad(ImageView imageView, String url, int pageIndex) {
    ContentPhotosDownloader downloader = AsyncDrawable.getTask(imageView);
    boolean shouldStart = true;
    if (downloader != null) {
      if (downloader.getPageIndex() == pageIndex && url.equals(downloader.getUrl())) {
        shouldStart = false;
      } else {
        downloader.cancel(true);
      }
    }
    return shouldStart;
  }

  @SuppressWarnings("deprecation")
  public GalleryFlipItem(Context context, GalleryPage mGalleryPage, FlipViewController controller,
                         int pageIndex) {
    super(context);
    mContext = context;

    LayoutInflater
        inflater =
        (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    inflater.inflate(R.layout.activity_filp_galleryflipitem, this);

    pd = (ProgressBar) findViewById(R.id.gallery_flip_item_background_progressbar);
    imgBackground = (ImageView) findViewById(R.id.gallery_flip_item_background_imageview);

    lnlPlace = (LinearLayout) findViewById(R.id.gallery_flip_item_place_linearlayout);

    imgIcon = (ImageView) findViewById(R.id.gallery_flip_item_place_icon_imageview);
    txtName = (TextView) findViewById(R.id.gallery_flip_item_place_name_textview);
    txtDistrict = (TextView) findViewById(R.id.gallery_flip_item_place_district_textview);
    txtCity = (TextView) findViewById(R.id.gallery_flip_item_place_city_textview);

    int measuredwidth = 0;
    int measuredheight = 0;
    WindowManager w = ((Activity) context).getWindowManager();

    Display d = w.getDefaultDisplay();
    measuredwidth = d.getWidth();
    measuredheight = d.getHeight();

    //notes: it's not the right approach to make the background fill its parent, using a RelativeLayout could be much better
    imgBackground.setLayoutParams(new LayoutParams(measuredwidth, measuredheight));

    refreshView(mGalleryPage, controller, pageIndex);
  }
}
