package com.simplecurrencyconverter.fragments;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;

import com.simplecurrencyconverter.R;
import com.simplecurrencyconverter.utils.ConversionRate;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.ParseException;
import java.util.Locale;

/**
 * A {@link Fragment} that contains currency conversion widgets.
 */
public class ConvertFragment extends Fragment {

    private final DecimalFormat inputAmountFormatter = getAmountFormatter("###,###.##");
    private final DecimalFormat outputAmountFormatter = getAmountFormatter("###,##0.00");

    private DecimalFormat getAmountFormatter(String formatPattern) {
        DecimalFormatSymbols symbols = new DecimalFormatSymbols(Locale.US);
        symbols.setGroupingSeparator(' ');
        return new DecimalFormat(formatPattern, symbols);
    }

    private final String emptyAmount = "0";

    private boolean allowAmountUpdate = true;

    private ConversionRate mConversionRate;

    /**
     * Creates an instance of the fragment.
     */
    public ConvertFragment() {
    }

    /**
     * Sets the conversion rate and currencies to show.
     *
     * @param conversionRate  a {@link com.simplecurrencyconverter.utils.ConversionRate} object that
     *                        contains the currencies and their conversion rate.
     */
    public void setConversionRate(ConversionRate conversionRate) {
        mConversionRate = conversionRate;
        addCurrencyListeners(getView());
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_convert, container, false);
    }

    private void addCurrencyListeners(View view) {
        EditText krwEditText = (EditText) view.findViewById(R.id.krw_amount);
        EditText eurEditText = (EditText) view.findViewById(R.id.eur_amount);

        addAmountChangedListeners(krwEditText, eurEditText, mConversionRate.getFixedCurrencyInVariableCurrencyRate());
        addFocusChangedListener(krwEditText);

        addAmountChangedListeners(eurEditText, krwEditText, mConversionRate.getVariableCurrencyInFixedCurrencyRate());
        addFocusChangedListener(eurEditText);
    }

    private void addAmountChangedListeners(final EditText editText, final EditText otherEditText, final BigDecimal multiplier) {
        editText.addTextChangedListener(new TextWatcher() {
            @Override
            public void afterTextChanged(Editable s) {
                updateOtherAmount(s, otherEditText, multiplier);
            }

            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
            }
        });
    }

    private void addFocusChangedListener(EditText editText) {
        editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
            @Override
            public void onFocusChange(View v, boolean hasFocus) {
                if (!hasFocus) {
                    updateLostFocusAmount((EditText) v);
                }
            }
        });
    }

    private void updateOtherAmount(Editable changedText, EditText editTextToChange, BigDecimal multiplier) {
        if (!allowAmountUpdate) {
            allowAmountUpdate = true;
            return;
        }
        allowAmountUpdate = false;

        String formattedOutputAmount;
        if (changedText.toString().length() == 0) {
            formattedOutputAmount = "";
        }
        else {
            BigDecimal inputAmount = parseDecimal(changedText.toString());
            BigDecimal outputAmount = inputAmount.multiply(multiplier).setScale(2, RoundingMode.HALF_EVEN);
            formattedOutputAmount = formatAmount(outputAmount, outputAmountFormatter);
        }
        editTextToChange.setText(formattedOutputAmount);
    }

    private void updateLostFocusAmount(EditText editText) {
        BigDecimal amount = parseDecimal(editText.getText().toString());
        String formattedOutputAmount = formatAmount(amount, inputAmountFormatter);
        // Empty the other amount too if the amount that lost focus was emptied
        allowAmountUpdate = formattedOutputAmount.length() == 0;
        editText.setText(formattedOutputAmount);
    }

    private BigDecimal parseDecimal(String s) {
        try {
            return new BigDecimal(inputAmountFormatter.parse(s).doubleValue());
        }
        catch (NumberFormatException e) {
            return new BigDecimal(0);
        }
        catch (ParseException e) {
            return new BigDecimal(0);
        }
    }

    private String formatAmount(BigDecimal amount, DecimalFormat formatter) {
        String formattedValue = formatter.format(amount.doubleValue());
        return formattedValue.equals(emptyAmount) ? "" : formattedValue;
    }
}

@@ -726,78 +726,42 @@
 nal 
-DecimalFormat inputAmountFormatter = getAmountFormatter(%22###,###.##%22);
+static String EMPTY_AMOUNT = %220%22;%0A
 %0A   
@@ -789,19 +789,19 @@
 lFormat 
-out
+mIn
 putAmoun
@@ -843,17 +843,16 @@
 #,##
-0.00
+#.##
 %22);%0A
-%0A
     
@@ -859,16 +859,22 @@
 private 
+final 
 DecimalF
@@ -879,18 +879,22 @@
 lFormat 
-ge
+mOutpu
 tAmountF
@@ -905,259 +905,43 @@
 tter
-(String formatPattern) %7B%0A        DecimalFormatSymbols symbols = new DecimalFormatSymbols(Locale.US);%0A        symbols.setGroupingSeparator(' ');%0A        return new DecimalFormat(formatPattern, symbols);%0A    %7D%0A%0A    private final String emptyAmount = %22
+ = getAmountFormatter(%22###,##0.0
 0%22
+)
 ;%0A%0A 
@@ -959,17 +959,18 @@
 boolean 
-a
+mA
 llowAmou
@@ -2663,33 +2663,32 @@
 ;%0A            %7D%0A
-%0A
             @Ove
@@ -2796,25 +2796,24 @@
           %7D%0A
-%0A
             
@@ -3435,17 +3435,18 @@
    if (!
-a
+mA
 llowAmou
@@ -3461,33 +3461,34 @@
 ) %7B%0A            
-a
+mA
 llowAmountUpdate
@@ -3526,33 +3526,34 @@
       %7D%0A        
-a
+mA
 llowAmountUpdate
@@ -3964,17 +3964,18 @@
 Amount, 
-o
+mO
 utputAmo
@@ -4256,17 +4256,18 @@
 amount, 
-i
+mI
 nputAmou
@@ -4368,17 +4368,18 @@
         
-a
+mA
 llowAmou
@@ -4578,17 +4578,18 @@
 Decimal(
-i
+mI
 nputAmou
@@ -5006,19 +5006,20 @@
 als(
-emptyAmount
+EMPTY_AMOUNT
 ) ? 
@@ -5044,11 +5044,264 @@
 e;%0A    %7D
+%0A%0A    private DecimalFormat getAmountFormatter(String formatPattern) %7B%0A        DecimalFormatSymbols symbols = new DecimalFormatSymbols(Locale.US);%0A        symbols.setGroupingSeparator(' ');%0A        return new DecimalFormat(formatPattern, symbols);%0A    %7D
 %0A%7D%0A

Clean up ConvertFragment, use m-prefixed member variables