nheyek/SDP-2018

View on GitHub
app/src/main/java/ch/epfl/sweng/studyup/questions/AddOrEditQuestionActivity.java

Summary

Maintainability
B
6 hrs
Test Coverage
package ch.epfl.sweng.studyup.questions;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.TextView;
import android.widget.Toast;

import java.io.File;
import java.io.FileDescriptor;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import ch.epfl.sweng.studyup.R;
import ch.epfl.sweng.studyup.firebase.FileStorage;
import ch.epfl.sweng.studyup.firebase.Firestore;
import ch.epfl.sweng.studyup.player.Player;
import ch.epfl.sweng.studyup.teacher.QuestsActivityTeacher;
import ch.epfl.sweng.studyup.utils.Constants;
import ch.epfl.sweng.studyup.utils.Constants.Course;
import ch.epfl.sweng.studyup.utils.imagePathGetter.imagePathGetter;
import ch.epfl.sweng.studyup.utils.imagePathGetter.mockImagePathGetter;
import ch.epfl.sweng.studyup.utils.imagePathGetter.pathFromGalleryGetter;
import ch.epfl.sweng.studyup.utils.navigation.NavigationStudent;

import static ch.epfl.sweng.studyup.utils.Constants.COLOR_SETTINGS_KEYWORD;
import static ch.epfl.sweng.studyup.utils.Constants.MOCK_UUID;
import static ch.epfl.sweng.studyup.utils.Constants.SETTINGS_COLOR_DARK;
import static ch.epfl.sweng.studyup.utils.Constants.SETTINGS_COLOR_RED;
import static ch.epfl.sweng.studyup.utils.Constants.USER_PREFS;
import static ch.epfl.sweng.studyup.utils.GlobalAccessVariables.MOCK_ENABLED;
import static ch.epfl.sweng.studyup.utils.Utils.getStringListFromCourseList;
import static ch.epfl.sweng.studyup.utils.Utils.setupToolbar;

@SuppressWarnings("HardCodedStringLiteral")
public class AddOrEditQuestionActivity extends NavigationStudent {
    private static final String TAG = "AddOrEditQuestionAct";

    private static final int READ_REQUEST_CODE = 42;
    private Uri imageURI = null;

    private RadioGroup langRadioGroup;
    private imagePathGetter getPath;
    private Course chosenCourse;
    public long chosenDuration;
    private TextView view_chosen_duration;
    private Bitmap bitmap = null;
    private boolean isNewQuestion = true;
    private Question question;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_add_edit_question);
        setupToolbar(this);

        Intent intent = getIntent();
        Question question = (Question) intent.getSerializableExtra(AddOrEditQuestionActivity.class.getSimpleName());

        view_chosen_duration = findViewById(R.id.chosen_duration_text);
        view_chosen_duration.setText(getString(R.string.chosen_duration) + getString(R.string.time_constraint_text));
        //No time limit by default
        chosenDuration = 0;

        // Setup path getter
        if (MOCK_ENABLED) {
            getPath = new mockImagePathGetter(this, READ_REQUEST_CODE);
        } else {
            Firestore.get().loadQuestions(this);
            getPath = new pathFromGalleryGetter(this, READ_REQUEST_CODE);
        }

        if(question != null) {
            if(!MOCK_ENABLED) findViewById(R.id.progressBar).setVisibility(View.VISIBLE);
            this.question = question;
            isNewQuestion = false;
            int trueFalseOrMCQ = question.isTrueFalse() ? R.id.true_false_radio : R.id.mcq_radio;
            int langButtonId = question.getLang().equals("en") ? R.id.radio_en : R.id.radio_fr;
            chosenCourse = Course.valueOf(question.getCourseName());
            AddOrEditQuestionActivityHelperMethods.setupEditQuestion(this, trueFalseOrMCQ, langButtonId, question.getTitle());
        }

        AddOrEditQuestionActivityHelperMethods.addRadioListener(this);
    }

    /**
     * Methods present to make the refactor of the class possible, used to retrieve the state of the question
     * or to set fields.
     */
    protected boolean isNewQuestion() {
        return isNewQuestion;
    }
    protected boolean isTrueFalse() {
        return question.isTrueFalse();
    }
    protected int getAnswer() {
        return question.getAnswer();
    }
    protected String getId() {
        return question.getQuestionId();
    }
    protected void setBitmap(Bitmap b) {
        bitmap = b;
    }
    protected Course getChosenCourse() {
        return chosenCourse;
    }
    /**
     * Function called when the user wants to choose an image in gallery    
     * @param current the current view
     */
    public void performFileSearch(View current) {
        getPath.getFilePath();
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent resultData) {
        // The ACTION_OPEN_DOCUMENT intent was sent with the request code
        // READ_REQUEST_CODE. If the request code seen here doesn't match, it's the
        // response to some other intent, and the code below shouldn't run at all.
        if (requestCode == READ_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
            // The document selected by the user won't be returned in the intent.
            // Instead, a URI to that document will be contained in the return intent
            // provided to this method as a parameter.
            // Pull that URI using resultData.getData().
            if (resultData != null) {
                imageURI = resultData.getData();
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        ImageView displayImage = findViewById(R.id.addQuestion_display_image);
                        try {
                            Bitmap image_bitmap = getBitmapFromUri(imageURI);
                            displayImage.setImageBitmap(image_bitmap);
                            //TextView displayName = findViewById(R.id.display_question_path);
                            //displayName.setVisibility(View.GONE);
                        } catch (IOException e) {
                            Log.e(TAG, "An error occurred when displaying the image");
                        }
                        /*TextView displayName = findViewById(R.id.display_question_path);
                        displayName.setText(imageURI.toString());*/
                    }
                });
            }
        }
    }


    public void addQuestion(View current) {
        RadioGroup imageTextRadioGroup = findViewById(R.id.text_or_image_radio_group), trueFalseRadioGroup = findViewById(R.id.true_false_or_mcq_radio_group);
        if (!(imageURI != null || bitmap != null || imageTextRadioGroup.getCheckedRadioButtonId() == R.id.text_radio_button)) return;
        RadioGroup answerGroup = findViewById(R.id.question_radio_group);
        RadioButton checkedButton = findViewById(answerGroup.getCheckedRadioButtonId());
        //get the tag of the button to know the answer number
        int answerNumber = Integer.parseInt(checkedButton.getTag().toString()) - 1;


        boolean isTrueFalseQuestion = trueFalseRadioGroup.getCheckedRadioButtonId() == R.id.true_false_radio;

        langRadioGroup = findViewById(R.id.lang_radio_group);
        String langQuestion = langRadioGroup.getCheckedRadioButtonId() == R.id.radio_en ? "en" : "fr";
        String newQuestionID = isNewQuestion ? getUUID() : question.getQuestionId();

        EditText newQuestionTitleView = findViewById(R.id.questionTitle);
        String newQuestionTitle = newQuestionTitleView.getText().toString();

        File questionFile;

        if (imageTextRadioGroup.getCheckedRadioButtonId() == R.id.image_radio_button) {
            //Delete the txt file, if there was any
            FileStorage.getProblemImageRef(Uri.parse(newQuestionID + ".txt")).delete();
            questionFile = setupFileImage(newQuestionID);
        } else {
            //If the edited question goes from image to text, we delete the image from firebase
            FileStorage.getProblemImageRef(Uri.parse(newQuestionID + ".png")).delete();
            questionFile = setupFileText(newQuestionID);
            if(questionFile == null) return;
        }

        Log.e(TAG, "create the question");
        if (newQuestionTitle.length() == 0) {
            Toast.makeText(this.getApplicationContext(), getString(R.string.text_insert_title_for_question), Toast.LENGTH_SHORT).show();
            return;
        }

        if(chosenCourse==null){
            Toast.makeText(this.getApplicationContext(), getString(R.string.text_select_course_for_question), Toast.LENGTH_SHORT).show();
            return;
        }
        String questionCourseName = chosenCourse.name();

        Question newQuestion = new Question(newQuestionID, newQuestionTitle, isTrueFalseQuestion, answerNumber, questionCourseName, langQuestion, chosenDuration);

        // Upload the problem image file to the Firebase Storage server
        FileStorage.uploadProblemImage(questionFile);
        // Add question to FireStore
        Firestore.get().addQuestion(newQuestion);

        if(isNewQuestion) {
            Toast.makeText(this.getApplicationContext(), getString(R.string.question_added), Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(this.getApplicationContext(), getString(R.string.question_edited), Toast.LENGTH_SHORT).show();
        }
        finish();
    }

    private File setupFileImage(String ID) {
        File questionFile = new File(this.getApplicationContext().getFilesDir(), ID + ".png");
        try {
            Bitmap imageBitmap = imageURI == null ? bitmap : getBitmapFromUri(imageURI);
            FileOutputStream out = new FileOutputStream(questionFile);
            imageBitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
            out.close();
        } catch (IOException e) {
            Log.e(TAG, e.getMessage());
        }

        return questionFile;
    }

    private File setupFileText(String ID) {
        try {
            Log.e(TAG, "text selected write file");
            File questionFile = new File(this.getApplicationContext().getFilesDir(), ID + ".txt");
            FileWriter writer = new FileWriter(questionFile);
            TextView questionTextView = findViewById(R.id.questionText);
            String questionData = questionTextView.getText().toString();
            if (questionData.isEmpty()) {
                Toast.makeText(this.getApplicationContext(), getString(R.string.cant_add_question_with_empty_text), Toast.LENGTH_SHORT).show();
                return null;
            }
            writer.write(questionData);
            writer.close();

            return questionFile;
        } catch (IOException e) {
            Log.e("Exception", "File write failed: " + e.toString());
        }

        return null;
    }

    private String getUUID() {
        if (MOCK_ENABLED) {
            return MOCK_UUID;
        } else {
            return UUID.randomUUID().toString();
        }
    }

    private Bitmap getBitmapFromUri(Uri uri) throws IOException {
        ParcelFileDescriptor parcelFileDescriptor =
                getContentResolver().openFileDescriptor(uri, "r");
        FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
        Bitmap image = BitmapFactory.decodeFileDescriptor(fileDescriptor);
        parcelFileDescriptor.close();
        return image;
    }

    public void onClickCourseChoice(View view) {
        String col = getSharedPreferences(USER_PREFS, MODE_PRIVATE)
                .getString(COLOR_SETTINGS_KEYWORD, SETTINGS_COLOR_RED);
        AlertDialog.Builder courseChoiceBuilder = col.equals(SETTINGS_COLOR_DARK) ?
                new AlertDialog.Builder(this, AlertDialog.THEME_DEVICE_DEFAULT_DARK) : new AlertDialog.Builder(this);
        courseChoiceBuilder.setTitle(getString(R.string.course_for_this_quest));

        final List<Course> courses = Player.get().isTeacher() ?
                Player.get().getCoursesTeached() : Player.get().getCoursesEnrolled();
        ArrayList<String> stringList = getStringListFromCourseList(courses, true);
        final ArrayList<String> stringListName = getStringListFromCourseList(courses, false);
        final String[] coursesArray = stringList.toArray(new String[stringList.size()]);
        courseChoiceBuilder.setItems(coursesArray, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                chosenCourse = Course.valueOf(stringListName.get(which));
                ((TextView) findViewById(R.id.chosenCourseTextView)).setText(getString(R.string.chosen_course_for_question)+chosenCourse.toString());
            }
        });
        courseChoiceBuilder.setNegativeButton(getString(R.string.cancel), null);
        courseChoiceBuilder.create().show();
    }

    public void onClickDurationChoice(View view) {
        String col = getSharedPreferences(USER_PREFS, MODE_PRIVATE)
                .getString(COLOR_SETTINGS_KEYWORD, SETTINGS_COLOR_RED);
        AlertDialog.Builder durationChoiceBuilder = col.equals(SETTINGS_COLOR_DARK) ?
                new AlertDialog.Builder(this, AlertDialog.THEME_DEVICE_DEFAULT_DARK) : new AlertDialog.Builder(this);
        durationChoiceBuilder.setTitle(R.string.duration);

        ArrayList<String> durationChoice = new ArrayList<>(Constants.durationChoice);
        String[] durationChoiceArray = durationChoice.toArray(new String[durationChoice.size()]);
        durationChoiceBuilder.setItems(durationChoiceArray, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                chosenDuration = Constants.durationCorrespond.get(which);
                if (chosenDuration == 0) {
                    view_chosen_duration.setText(getString(R.string.chosen_duration) + getString(R.string.time_constraint_text));
                } else {
                    view_chosen_duration.setText(getString(R.string.chosen_duration) + Constants.durationChoice.get(which));
                }
            }
        });
        durationChoiceBuilder.setNegativeButton(getString(R.string.cancel), null);
        durationChoiceBuilder.create().show();
    }

    public void onBackButtonAddQuestion(View view) {
        startActivity(new Intent(this.getApplicationContext(), QuestsActivityTeacher.class));
    }

}