from flask import Flask, request
from flask_cors import CORS
import json
import werkzeug
import cv2
from tensorflow.keras.models import load_model
import numpy as np
from rome_numeric_rec.ocr import get_rome_number
from rome_numeric_rec.rome_to_number import roman_to_int
import base64
from imageio import imread
import io
from equation_solver.es import get_ans_from_image
from numeric_pattern_rec.LinearRegression import get_next_numbers_of_sequence
import numeric_pattern_rec.ocr as ocr

from keras.models import Sequential
from keras.layers import Dense, Activation, Flatten, Dropout
from keras.layers import Conv2D, MaxPooling2D

app = Flask(__name__)
CORS(app)

model = load_model('shape_rec/model.h5')

data_dic = {0: 'rectangle', 1: 'circle', 2: 'ellipse', 3: 'hexagon', 4: 'trangle', 5: 'square', 6: 'stars'}


@app.route('/equation_solver', methods=['GET', 'POST'])
def equation_solver():
    # for base 64 json input
    string_64 = request.json['image']
    string_64 = str(string_64).replace('image/webp;base64,', '')
    img = base_64_cv2(string_64)

    img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

    answer = get_ans_from_image(img_gray)

    return_str = '{ "answer" : "' + str(answer) + '" }'

    print(return_str)

    return json.loads(return_str)


@app.route('/number_pattern', methods=['GET', 'POST'])
def number_pattern():
    string_64 = request.json['image']
    string_64 = str(string_64).replace('image/webp;base64,', '')
    img = base_64_cv2(string_64)
    cv2.imwrite('upload/number_pattern.png', img)
    n = request.json['n']

    input_pattern = ocr.get_ocr('upload/number_pattern.png')
    input_list = []

    for i in input_pattern.split(','):

        try:
            input_list.append(int(str(i).replace(',', '').replace(' ', '')))
        except:
            pass

    y, img = get_next_numbers_of_sequence(5, input_list)

    base64_string = get_base_64(img)

    return_str = '{ "predict_values" : ' + str(y) + ', "plot" : "' + str(base64_string) + '" }'

    print(return_str)

    return json.loads(return_str)


@app.route('/rome_to_number', methods=['GET', 'POST'])
def rome_to_number():
    string_64 = request.json['image']
    string_64 = str(string_64).replace('image/webp;base64,', '')
    img = base_64_cv2(string_64)
    cv2.imwrite('upload/number_pattern.png', img)

    rome_text = get_rome_number(img).upper().replace(' ', '').replace('\n', '')
    print(rome_text)
    numeric_number = roman_to_int(rome_text)

    return_str = '{ "res" : ' + str(numeric_number) + ' }'

    print(return_str)

    return json.loads(return_str)


@app.route('/rome_to_number_new', methods=['GET', 'POST'])
def rome_to_number_new():
    string_64 = request.json['image']
    string_64 = str(string_64).replace('image/webp;base64,', '')
    img = base_64_cv2(string_64)
    cv2.imwrite('upload/number_pattern.png', img)

    rome_data_dic = {0: 'VI', 1: 'II', 2: 'I', 3: 'VII', 4: 'VIII', 5: 'IV', 6: 'IX', 7: 'V', 8: 'X', 9: 'III'}

    data = np.load('rome_numeric_rec/Processed_Data/data/data.npy')
    target = np.load('rome_numeric_rec/Processed_Data/data/target.npy')

    model = Sequential()

    model.add(Conv2D(256, (3, 3), input_shape=data.shape[1:]))
    model.add(Activation('relu'))
    model.add(MaxPooling2D(pool_size=(2, 2)))

    model.add(Conv2D(128, (3, 3)))
    model.add(Activation('relu'))
    model.add(MaxPooling2D(pool_size=(2, 2)))

    model.add(Flatten())

    model.add(Dropout(0.5))
    model.add(Dense(64, activation='relu'))

    model.add(Dense(4, activation='softmax'))

    model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])

    model.load_weights('rome_numeric_rec/model.h5')

    img = cv2.imread('upload/number_pattern.png', img)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    resized = cv2.resize(gray, (50, 50))
    normalized = resized / 255.0
    reshaped = np.reshape(normalized, (1, 50, 50, 1))

    result = model.predict(reshaped)
    label = np.argmax(result, axis=1)[0]
    prob = np.max(result, axis=1)[0]
    prob = round(prob, 2) * 100

    print('Confident : ', np.max(result, axis=1)[0])

    numeric_number = roman_to_int(rome_data_dic[np.argmax(result, axis=1)[0]])

    return_str = '{ "res" : ' + str(numeric_number) + ' }'

    print(return_str)

    return json.loads(return_str)


@app.route('/shape_classifier', methods=['GET', 'POST'])
def shape_classifier():
    string_64 = request.json['image']
    string_64 = str(string_64).replace('image/webp;base64,', '')
    img = base_64_cv2(string_64)
    cv2.imwrite('upload/number_pattern.png', img)

    img = np.asarray(img)
    img = cv2.resize(img, (32, 32))
    img = preProcessing(img)
    img = img.reshape(1, 32, 32, 1)
    classIndex = int(model.predict_classes(img))
    predictions = model.predict(img)
    # probVal = np.amax(predictions)
    a = np.amax(predictions) * 100
    x = "%.2f" % round(a, 2)
    print(classIndex)
    print(x)

    return_str = '{ "score" : "' + str(data_dic[classIndex]) + '" }'

    print(return_str)

    return json.loads(return_str)


def preProcessing(img):
    img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    img = cv2.equalizeHist(img)
    img = img / 255
    return img


def base_64_cv2(string_64):
    img = imread(io.BytesIO(base64.b64decode(string_64)))
    cv2_img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)
    return cv2_img


def get_base_64(img):
    retval, buffer = cv2.imencode('.jpg', img)
    jpg_as_text = base64.b64encode(buffer)
    return jpg_as_text


if __name__ == '__main__':
    app.run(host="0.0.0.0", port=5500, debug=True)
