package com.jachdev.consumerprotection.ui.classifier;

import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
import butterknife.BindView;
import butterknife.OnClick;

import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;

import com.jachdev.commonlibs.base.BaseActivity;
import com.jachdev.commonlibs.validator.Validator;
import com.jachdev.commonlibs.widget.CustomEditText;
import com.jachdev.commonlibs.widget.CustomTextView;
import com.jachdev.consumerprotection.R;
import com.jachdev.consumerprotection.data.Nutrition;
import com.jachdev.consumerprotection.data.NutritionResponse;
import com.jachdev.consumerprotection.ui.bot.BotActivity;
import com.jachdev.consumerprotection.ui.bot.BotViewModel;
import com.jachdev.consumerprotection.util.Classifier;
import com.jachdev.consumerprotection.util.TensorFlowImageClassifier;

import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

public class ClassifierActivity extends BaseActivity {//for CameraIntent
    private int PICK_IMAGE_REQUEST = 1;

    //setUp for tensorflow
    public static final int INPUT_SIZE = 224;
    public static final int IMAGE_MEAN = 128;
    public static final float IMAGE_STD = 128.0f;
    public static final String INPUT_NAME = "input";
    public static final String OUTPUT_NAME = "final_result";
    public static final String MODEL_FILE = "file:///android_asset/rounded_graph.pb";
    public static final String LABEL_FILE = "file:///android_asset/retrained_labels.txt";

    private ClassifierViewModel classifierViewModel;

    @BindView(R.id.et_search)
    CustomEditText etSearch;

    @BindView(R.id.nname)
    CustomTextView nname;
    @BindView(R.id.sugar_g)
    CustomTextView sugar_g;
    @BindView(R.id.fiber_g)
    CustomTextView fiber_g;
    @BindView(R.id.serving_size_g)
    CustomTextView serving_size_g;
    @BindView(R.id.sodium_mg)
    CustomTextView sodium_mg;
    @BindView(R.id.potassium_mg)
    CustomTextView potassium_mg;
    @BindView(R.id.fat_saturated_g)
    CustomTextView fat_saturated_g;
    @BindView(R.id.fat_total_g)
    CustomTextView fat_total_g;
    @BindView(R.id.calories)
    CustomTextView calories;
    @BindView(R.id.cholesterol_mg)
    CustomTextView cholesterol_mg;
    @BindView(R.id.protein_g)
    CustomTextView protein_g;
    @BindView(R.id.carbohydrates_total_g)
    CustomTextView carbohydrates_total_g;

    public Classifier classifier;
    public Executor executor = Executors.newSingleThreadExecutor();
    public ImageView iV1;

    @Override
    protected int layoutRes() {
        return R.layout.activity_classifier;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        classifierViewModel = new ViewModelProvider(this).get(ClassifierViewModel.class);

        observeViewModels();
        init();

    }

    @OnClick(R.id.btn_search)
    void onSearchClick(){
        if(Validator.isEditTextEmpty(etSearch, getString(R.string.cl_error_input_valid_field))){

            findViewById(R.id.nutrition_layout).setVisibility(View.GONE);
            classifierViewModel.getNutrition(etSearch.getTrimText());
            etSearch.setAnyText("");
        }
    }

    private void observeViewModels() {
        classifierViewModel.getNutritionData().observe(ClassifierActivity.this, mNutritionObserve);
    }

    private void init() {

        iV1 = (ImageView) findViewById(R.id.imageView1);
        initTensorFlowAndLoadModel();
    }

    private void initTensorFlowAndLoadModel() {
        executor.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    classifier = TensorFlowImageClassifier.create(
                            getAssets(),
                            MODEL_FILE,
                            LABEL_FILE,
                            INPUT_SIZE,
                            IMAGE_MEAN,
                            IMAGE_STD,
                            INPUT_NAME,
                            OUTPUT_NAME);
                } catch (final Exception e) {
                    throw new RuntimeException("Error initializing TensorFlow!", e);
                }
            }
        });
    }

    public List<Classifier.Recognition> analyse(Bitmap bitmap)
    {
        bitmap = Bitmap.createScaledBitmap(bitmap, INPUT_SIZE, INPUT_SIZE, false);
        final List<Classifier.Recognition> results = classifier.recognizeImage(bitmap);
        return results;
    }

    public void selectPhoto(View v)
    {
        Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
        photoPickerIntent.setType("image/*");
        startActivityForResult(photoPickerIntent, PICK_IMAGE_REQUEST);
    }
    @Override
    protected void onActivityResult(int reqCode, int resultCode, Intent data) {
        super.onActivityResult(reqCode, resultCode, data);
        if (resultCode == RESULT_OK) {
            try
            {
                final Uri imageUri = data.getData();
                final InputStream imageStream = getContentResolver().openInputStream(imageUri);
                final Bitmap selectedImage = BitmapFactory.decodeStream(imageStream);
                List<Classifier.Recognition> results = analyse(selectedImage);
                etSearch.setText(results.get(0).toString());
                setPicture(selectedImage);

            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }
    }
    //set Picture in the ImageView (iV1)
    public void setPicture(Bitmap bp)
    {
        Bitmap scaledBp =  Bitmap.createScaledBitmap(bp, iV1.getWidth(), iV1.getHeight(), false);
        iV1.setImageBitmap(scaledBp);
        iV1.setScaleType(ImageView.ScaleType.CENTER_CROP);
    }

    private Observer<? super List<Nutrition>> mNutritionObserve = new Observer<List<Nutrition>>() {
        @Override
        public void onChanged(List<Nutrition> responses) {
            if(responses == null || responses.size() == 0)return;

            Nutrition n = responses.get(0);

            nname.setAnyText(getString(R.string.nname, n.getName()));
            sugar_g.setAnyText(getString(R.string.sugar_g, n.getSugar_g() + ""));
            fiber_g.setAnyText(getString(R.string.fiber_g, n.getFiber_g() + ""));
            serving_size_g.setAnyText(getString(R.string.serving_size_g, n.getServing_size_g() + ""));
            sodium_mg.setAnyText(getString(R.string.sodium_mg, n.getSodium_mg() + ""));
            potassium_mg.setAnyText(getString(R.string.potassium_mg, n.getPotassium_mg() + ""));
            fat_saturated_g.setAnyText(getString(R.string.fat_saturated_g, n.getFat_saturated_g() + ""));
            fat_total_g.setAnyText(getString(R.string.fat_total_g, n.getFat_total_g() + ""));
            calories.setAnyText(getString(R.string.calories, n.getCalories() + ""));
            cholesterol_mg.setAnyText(getString(R.string.cholesterol_mg, n.getCholesterol_mg() + ""));
            protein_g.setAnyText(getString(R.string.protein_g, n.getProtein_g() + ""));
            carbohydrates_total_g.setAnyText(getString(R.string.carbohydrates_total_g, n.getCarbohydrates_total_g() + ""));

            findViewById(R.id.nutrition_layout).setVisibility(View.VISIBLE);
        }
    };
}