/*
 * Copyright (C) The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.google.android.gms.samples.vision.ocrreader;

import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;

import com.google.android.gms.samples.vision.ocrreader.ui.camera.GraphicOverlay;
import com.google.android.gms.vision.text.Text;
import com.google.android.gms.vision.text.TextBlock;

import java.util.HashMap;
import java.util.List;

/**
 * Graphic instance for rendering TextBlock position, size, and ID within an associated graphic
 * overlay view.
 */
public class OcrGraphic extends GraphicOverlay.Graphic {

    private int mId;

    private static final int TEXT_COLOR = Color.WHITE;

    private static Paint sRectPaint;
    private static Paint sTextPaint;
    private final TextBlock mText;

    OcrGraphic(GraphicOverlay overlay, TextBlock text) {
        super(overlay);

        mText = text;

        if (sRectPaint == null) {
            sRectPaint = new Paint();
            sRectPaint.setColor(TEXT_COLOR);
            sRectPaint.setStyle(Paint.Style.STROKE);
            sRectPaint.setStrokeWidth(4.0f);
        }

        if (sTextPaint == null) {
            sTextPaint = new Paint();
            sTextPaint.setColor(TEXT_COLOR);
            sTextPaint.setTextSize(54.0f);
        }
        // Redraw the overlay, as this graphic has been added.
        postInvalidate();
    }

    public int getId() {
        return mId;
    }

    public void setId(int id) {
        this.mId = id;
    }

    public TextBlock getTextBlock() {
        return mText;
    }

    /**
     * Checks whether a point is within the bounding box of this graphic.
     * The provided point should be relative to this graphic's containing overlay.
     * @param x An x parameter in the relative context of the canvas.
     * @param y A y parameter in the relative context of the canvas.
     * @return True if the provided point is contained within this graphic's bounding box.
     */
    public boolean contains(float x, float y) {
        TextBlock text = mText;
        if (text == null) {
            return false;
        }
        RectF rect = new RectF(text.getBoundingBox());
        rect.left = translateX(rect.left);
        rect.top = translateY(rect.top);
        rect.right = translateX(rect.right);
        rect.bottom = translateY(rect.bottom);
        return (rect.left < x && rect.right > x && rect.top < y && rect.bottom > y);
    }

    /**
     * Draws the text block annotations for position, size, and raw value on the supplied canvas.
     */
    @Override
    public void draw(Canvas canvas) {
        TextBlock text = mText;
        if (text == null) {
            return;
        }

        // Draws the bounding box around the TextBlock.
        RectF rect = new RectF(text.getBoundingBox());
        rect.left = translateX(rect.left);
        rect.top = translateY(rect.top);
        rect.right = translateX(rect.right);
        rect.bottom = translateY(rect.bottom);
        canvas.drawRect(rect, sRectPaint);

        // Break the text into multiple lines and draw each one according to its own bounding box.
        List<? extends Text> textComponents = text.getComponents();
        for(Text currentText : textComponents) {
            float left = translateX(currentText.getBoundingBox().left);
            float bottom = translateY(currentText.getBoundingBox().bottom);
            String faen = "";
            for(Character c: text.getValue().toCharArray()){
                faen+=char_to_braille(c);
            }
            canvas.drawText(faen, left, bottom, sTextPaint);
        }
    }
    Character char_to_braille(Character c){
        HashMap<Character, Character> map  = new HashMap<>();
        map.put(' ', ' ');
        map.put('!', '⠮');
        map.put('\"', '⠐');
        map.put('#' , '⠼');
        map.put('$' , '⠫');
        map.put('%' , '⠩');
        map.put('&' , '⠯');
        map.put('\'', '⠄' );
        map.put('(','⠷');
        map.put(')' ,'⠾');
        map.put('*' ,'⠡');
        map.put('+' ,'⠬');
        map.put(',','⠠');
        map.put('-' ,'⠤');
        map.put('.' ,'⠨');
        map.put('/' ,'⠌');
        map.put('0' ,'⠴');
        map.put('1' ,'⠂');
        map.put('2' ,'⠆' );
        map.put('3' ,'⠒' );
        map.put('4' ,'⠲' );
        map.put('5' ,'⠢' );
        map.put('6' ,'⠖' );
        map.put('7' ,'⠶' );
        map.put('8' ,'⠦' );
        map.put('9' ,'⠔' );
        map.put(':' ,'⠱' );
        map.put(';' ,'⠰' );
        map.put('<' ,'⠣' );
        map.put('>' ,'⠜' );
        map.put('?' ,'⠹' );
        map.put('=' ,'⠿' );
        map.put('@' ,'⠈' );
        map.put('A' ,'⠁' );
        map.put('B' ,'⠃' );
        map.put('C' ,'⠉' );
        map.put('D' ,'⠙' );
        map.put('E' ,'⠑' );
        map.put('F' ,'⠋' );
        map.put('G' ,'⠛' );
        map.put('H' ,'⠓' );
        map.put('I' ,'⠊' );
        map.put('J' ,'⠚' );
        map.put('K' ,'⠅' );
        map.put('L' ,'⠇' );
        map.put('M' ,'⠍' );
        map.put('N' ,'⠝' );
        map.put('O' ,'⠕' );
        map.put('P' ,'⠏' );
        map.put('Q' ,'⠟' );
        map.put('R' ,'⠗' );
        map.put('S' ,'⠎' );
        map.put('T' ,'⠞' );
        map.put('U' ,'⠥' );
        map.put('V' ,'⠽' );
        map.put('W' ,'⠺' );
        map.put('X' ,'⠭' );
        map.put('Y' ,'⠽' );
        map.put('Z' ,'⠵' );
        map.put('[' ,'⠪' );
        map.put('\\','⠳' );
        map.put(']' ,'⠻' );
        map.put('^' ,'⠘' );
        map.put('_' ,'⠸' );
        if(map.get(Character.toUpperCase(c)) != null){
            return map.get(Character.toUpperCase(c));
        } else {
            return c;
        }
    }
}
