package info.blockchain.wallet.ui;
import java.math.BigInteger;
import java.util.List;
import java.util.Map;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Matrix;
import android.util.Log;
import android.content.res.Resources;
//import android.util.Log;
public class TxBitmap {
public static int SENDING = 1;
public static int RECEIVING = 2;
private static int VERTICAL_FLIP = 1;
private static int HORIZONTAL_FLIP = 2;
private static TxBitmap instance = null;
private static Context context = null;
private static float REG_RES = 2.0f;
private List<Map.Entry<String, String>> addressValueEntryList;
public TxBitmap() { ; }
public TxBitmap(Context ctx, List<Map.Entry<String, String>> addressValueEntryList) {
this.setAddressValueEntryList(addressValueEntryList);
context = ctx;
}
public static TxBitmap getInstance(Context ctx) {
context = ctx;
if(instance == null) {
instance = new TxBitmap();
}
return instance;
}
public Bitmap createArrowsBitmap(int width, int type, int branches) {
if(type == SENDING) {
return tx_arrows(width, type, branches);
}
else {
return flip(tx_arrows(width, type, branches), HORIZONTAL_FLIP);
}
}
public Bitmap createListBitmap(int width) {
Resources resources = context.getResources();
float scale = resources.getDisplayMetrics().density;
if(scale > REG_RES) {
width += 160;
}
return tx_list(width);
}
private Bitmap flip(Bitmap src, int type) {
Matrix matrix = new Matrix();
// vertical
if(type == VERTICAL_FLIP) {
// y = y * -1
matrix.preScale(1.0f, -1.0f);
}
// horizontal
else {
// x = x * -1
matrix.preScale(-1.0f, 1.0f);
}
return Bitmap.createBitmap(src, 0, 0, src.getWidth(), src.getHeight(), matrix, true);
}
@SuppressLint("NewApi")
private Bitmap tx_list(int width) {
Resources resources = context.getResources();
float scale = resources.getDisplayMetrics().density;
float fX = 10.0f;
float fY = (scale <= REG_RES) ? 35.0f : 42.0f;
float vOffset = (scale <= REG_RES) ? 80.0f : 88.0f; // down step
float vOffsetAmount = (scale <= REG_RES) ? 26.0f : 40.0f;
float vXtraOffset = (scale <= REG_RES) ? 1.0f : 8.0f;
float szAddress = 15;
float szAmount = 12;
int bottomPadding = (scale <= REG_RES) ? 10 : 20;
final int branches = addressValueEntryList.size();
// Bitmap bm = Bitmap.createBitmap(resources.getDisplayMetrics(), width, ((int)(vOffset * branches)) + bottomPadding, Config.ARGB_8888);
Bitmap bm = Bitmap.createBitmap(width, ((int)(vOffset * branches)) + bottomPadding, Config.ARGB_8888);
Canvas canvas = new Canvas(bm);
Paint paintAddressLabel = new Paint(Paint.ANTI_ALIAS_FLAG);
paintAddressLabel.setColor(0xff87cefa);
paintAddressLabel.setTextSize((int)(szAddress * scale + 0.5f));
paintAddressLabel.setTypeface(TypefaceUtil.getInstance(context).getRobotoTypeface());
Paint paintAddressBTC = new Paint(Paint.ANTI_ALIAS_FLAG);
paintAddressBTC.setColor(Color.GRAY);
paintAddressBTC.setTextSize((int)(szAddress * scale + 0.5f));
paintAddressBTC.setTypeface(TypefaceUtil.getInstance(context).getRobotoTypeface());
Paint paintAmount = new Paint(Paint.ANTI_ALIAS_FLAG);
paintAmount.setColor(Color.GRAY);
paintAmount.setTextSize((int)(szAmount * scale + 0.5f));
paintAddressLabel.setTypeface(TypefaceUtil.getInstance(context).getRobotoBoldTypeface());
for(int i = 0; i < branches; i++) {
Map.Entry<String, String> addressValueEntry = addressValueEntryList.get(i);
String addressLabel = addressValueEntry.getKey();
String addressLabelConcat;
if (scale <= REG_RES) {
addressLabelConcat = BlockchainUtil.formatAddress(addressLabel, 7);
} else {
addressLabelConcat = BlockchainUtil.formatAddress(addressLabel, 15);
}
canvas.drawText(addressLabelConcat, fX, fY + (vOffset * i) + vXtraOffset, paintAddressLabel);
if(branches > 1) {
canvas.drawText(addressValueEntry.getValue(), fX, fY + (vOffset * i) + vOffsetAmount + vXtraOffset, paintAmount);
}
}
return bm;
}
@SuppressLint("NewApi")
private Bitmap tx_arrows(int width, int type, int branches) {
Resources resources = context.getResources();
float scale = resources.getDisplayMetrics().density;
float fStroke = 6.0f;
float fRadius = 8.0f; // filled circle at start of line
float fX = 15.0f;
float fY = (scale <= REG_RES) ? 30.0f : 36.0f;
float hOffset = 20.0f; // indent
float vOffset = (scale <= REG_RES) ? 80.0f : 88.0f; // down step
int bottomPadding = (scale <= REG_RES) ? 10 : 20;
// Bitmap bm = Bitmap.createBitmap(resources.getDisplayMetrics(), width, ((int)(vOffset * branches)) + bottomPadding, Config.ARGB_8888);
Bitmap bm = Bitmap.createBitmap(width, ((int)(vOffset * branches)) + bottomPadding, Config.ARGB_8888);
Canvas canvas = new Canvas(bm);
Paint paint = new Paint();
paint.setColor(type == SENDING ? BlockchainUtil.BLOCKCHAIN_RED : BlockchainUtil.BLOCKCHAIN_GREEN);
paint.setStrokeWidth(fStroke);
canvas.drawCircle(fX, fY, fRadius, paint);
canvas.drawLine(fX, fY, canvas.getWidth() - fX, fY, paint);
doArrowhead(canvas, fX, fY, canvas.getWidth() - ((fX - 10.0f) - 2.0f), fY, type);
if(branches > 1) {
int remaining_branches = branches - 1;
for(int i = 0; i < remaining_branches; i++) {
canvas.drawLine(fX + hOffset, fY, fX + hOffset, fY + (vOffset * (i + 1)), paint);
canvas.drawLine(fX + hOffset, fY + (vOffset * (i + 1)), canvas.getWidth() - (fX - 10.0f), fY + (vOffset * (i + 1)), paint);
doArrowhead(canvas, fX + hOffset, fY + (vOffset * (i + 1)), canvas.getWidth() - ((fX - 10.0f) - 2.0f), fY + (vOffset * (i + 1)), type);
}
}
return bm;
}
private void doArrowhead(Canvas canvas, float x0, float y0, float x1, float y1, int type) {
Paint paint = new Paint();
paint.setColor(type == SENDING ? BlockchainUtil.BLOCKCHAIN_RED : BlockchainUtil.BLOCKCHAIN_GREEN);
paint.setStyle(Paint.Style.FILL);
float deltaX = x1 - x0;
float deltaY = y1 - y0;
float frac = 0.065f; // arrow head size
float point_x_1 = x0 + ((1.0f - frac) * deltaX + frac * deltaY);
float point_y_1 = y0 + ((1.0f - frac) * deltaY - frac * deltaX);
float point_x_2 = x1;
float point_y_2 = y1;
float point_x_3 = x0 + ((1.0f - frac) * deltaX - frac * deltaY);
float point_y_3 = y0 + ((1.0f - frac) * deltaY + frac * deltaX);
Path path = new Path();
path.setFillType(Path.FillType.EVEN_ODD);
path.moveTo(point_x_1, point_y_1);
path.lineTo(point_x_2, point_y_2);
path.lineTo(point_x_3, point_y_3);
path.lineTo(point_x_1, point_y_1);
path.lineTo(point_x_1, point_y_1);
path.close();
canvas.drawPath(path, paint);
}
public List<Map.Entry<String, String>> getAddressValueEntryList() {
return addressValueEntryList;
}
public void setAddressValueEntryList(List<Map.Entry<String, String>> addressValueEntryList) {
this.addressValueEntryList = addressValueEntryList;
}
}