/*
 * Copyright (c) 2015 Diona Ltd.
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of Diona
 * ("Confidential Information"). You shall not disclose such Confidential Information
 * and shall use it only in accordance with the terms of the license agreement you
 * entered into with Diona.
 */
package org.odk.collect.android.views;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.support.annotation.NonNull;
import android.text.style.ImageSpan;

import java.lang.ref.WeakReference;

/**
 * An ImageSpan that centers its image with the text.
 */
public class CenteredImageSpan extends ImageSpan {

  private WeakReference<Drawable> mDrawableRef;

  /**
   * @param context
   *          the Context in which the span will be drawn.
   * @param resourceId
   *          the ID of the Drawable resource to be drawn.
   * @param verticalAlignment
   *          the vertical alignment of the span.
   */
  public CenteredImageSpan(final Context context, final int resourceId, final int verticalAlignment) {
    super(context, resourceId, verticalAlignment);
  }

  /**
   * @param context
   *          the Context in which the span will be drawn.
   * @param resourceId
   *          the ID of the Drawable resource to be drawn.
   */
  public CenteredImageSpan(final Context context, final int resourceId) {
    super(context, resourceId);
  }

  @Override
  public int getSize(final Paint paint, final CharSequence text, final int start, final int end,
      final Paint.FontMetricsInt fm) {
    final Drawable d = getCachedDrawable();
    final Rect rect = d.getBounds();

    if (fm != null) {
      final Paint.FontMetricsInt pfm = paint.getFontMetricsInt();
      // keep it the same as paint's fm
      fm.ascent = pfm.ascent;
      fm.descent = pfm.descent;
      fm.top = pfm.top;
      fm.bottom = pfm.bottom;
    }

    return rect.right;
  }

  @Override
  public void draw(@NonNull final Canvas canvas, final CharSequence text, final int start, final int end, final float x,
      final int top, final int y, final int bottom, @NonNull final Paint paint) {
    final Drawable b = getCachedDrawable();
    canvas.save();

    final int drawableHeight = b.getIntrinsicHeight();
    final int fontAscent = paint.getFontMetricsInt().ascent;
    final int fontDescent = paint.getFontMetricsInt().descent;
    final int transY = bottom - b.getBounds().bottom + // align bottom to bottom
        (drawableHeight - fontDescent + fontAscent) / 2; // align center to center

    canvas.translate(x, transY);
    b.draw(canvas);
    canvas.restore();
  }

  // Redefined locally because it is a private member from DynamicDrawableSpan
  private Drawable getCachedDrawable() {
    final WeakReference<Drawable> wr = mDrawableRef;
    Drawable d = null;

    if (wr != null) {
      d = wr.get();
    }

    if (d == null) {
      d = getDrawable();
      mDrawableRef = new WeakReference<Drawable>(d);
    }

    return d;
  }
}
