package it.integry.integrywmsnative.core.di;

import androidx.databinding.BindingAdapter;
import androidx.databinding.BindingConversion;
import androidx.constraintlayout.widget.Guideline;
import com.google.android.material.textfield.TextInputEditText;
import androidx.core.util.Pair;
import androidx.appcompat.widget.AppCompatCheckBox;
import androidx.appcompat.widget.AppCompatTextView;
import android.util.Log;
import android.view.View;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.RadioButton;
import android.widget.RadioGroup;

import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.util.Locale;

import androidx.databinding.Observable;
import it.integry.integrywmsnative.R;

public class Converters {

    @BindingConversion
    public static String convertBindableToString(BindableString bindableString) {
        return bindableString.get();
    }

    @BindingConversion
    public static boolean convertBindableToBoolean(BindableBoolean bindableBoolean) {
        return bindableBoolean.get();
    }

    @BindingAdapter("app:binding")
    public static void bindEditText(EditText view, final BindableString bindableString) {
        Pair<BindableString, TextWatcherAdapter> pair = (Pair) view.getTag(R.id.bound_observable);
        if (pair == null || pair.first != bindableString) {
            if (pair != null) {
                view.removeTextChangedListener(pair.second);
            }
            TextWatcherAdapter watcher = new TextWatcherAdapter() {
                @Override public void onTextChanged(CharSequence s, int start, int before, int count) {
                    bindableString.set(s.toString());
                }
            };
            view.setTag(R.id.bound_observable, new Pair<>(bindableString, watcher));
            view.addTextChangedListener(watcher);
        }
        String newValue = bindableString.get();
        if (!view.getText().toString().equals(newValue)) {
            view.setText(newValue);
        }
    }

    @BindingAdapter("app:binding")
    public static void bindTextInputEditText(TextInputEditText view, final BindableString bindableString) {
        Pair<BindableString, TextWatcherAdapter> pair = (Pair) view.getTag(R.id.bound_observable);
        if (pair == null || pair.first != bindableString) {
            if (pair != null) {
                view.removeTextChangedListener(pair.second);
            }
            TextWatcherAdapter watcher = new TextWatcherAdapter() {
                @Override public void onTextChanged(CharSequence s, int start, int before, int count) {
                    bindableString.set(s.toString());
                }
            };
            view.setTag(R.id.bound_observable, new Pair<>(bindableString, watcher));
            view.addTextChangedListener(watcher);
        }
        String newValue = bindableString.get();
        if (!view.getText().toString().equals(newValue)) {
            view.setText(newValue);
        }
    }

    @BindingAdapter("app:binding")
    public static void bindTextView(AppCompatTextView view, final BindableString bindableString) {
        Pair<BindableString, TextWatcherAdapter> pair = (Pair) view.getTag(R.id.bound_observable);
        if (pair == null || pair.first != bindableString) {
            if (pair != null) {
                view.removeTextChangedListener(pair.second);
            }
            TextWatcherAdapter watcher = new TextWatcherAdapter() {
                @Override public void onTextChanged(CharSequence s, int start, int before, int count) {
                    bindableString.set(s.toString());
                }
            };
            view.setTag(R.id.bound_observable, new Pair<>(bindableString, watcher));
            view.addTextChangedListener(watcher);
        }
        String newValue = bindableString.get();
        if (!view.getText().toString().equals(newValue)) {
            view.setText(newValue);
        }
    }

    @BindingAdapter("app:binding")
    public static void bindTextInputEditText(TextInputEditText view, final BindableFloat bindableFloat) {
        DecimalFormatSymbols otherSymbols = new DecimalFormatSymbols(Locale.getDefault());
        otherSymbols.setDecimalSeparator('.');
        otherSymbols.setGroupingSeparator(',');


        final DecimalFormat decimalFormat = new DecimalFormat();
        decimalFormat.setMaximumFractionDigits(3);
        decimalFormat.setDecimalFormatSymbols(otherSymbols);

        Pair<BindableFloat, TextWatcherAdapter> pair = (Pair) view.getTag(R.id.bound_observable);
        if (pair == null || pair.first != bindableFloat) {
            if (pair != null) {
                view.removeTextChangedListener(pair.second);
            }
            TextWatcherAdapter watcher = new TextWatcherAdapter() {
                @Override public void onTextChanged(CharSequence s, int start, int before, int count) {
                    try {
                        if(s.toString().trim().isEmpty()){
                            bindableFloat.set(null);
                        } else bindableFloat.set(decimalFormat.parse(s.toString()).floatValue());
                    } catch (Exception ex){
                        Log.e("FloatFormat", ex.getMessage());
                    }
                }
            };
            view.setTag(R.id.bound_observable, new Pair<>(bindableFloat, watcher));
            view.addTextChangedListener(watcher);
        }

        Float newValue = bindableFloat.get();
        if (!view.getText().toString().equals(decimalFormat.format(newValue))) {

            view.setText(decimalFormat.format(newValue));
            view.setSelection(view.getText().toString().length());
        }
    }

    @BindingAdapter("app:binding")
    public static void bindRadioGroup(RadioGroup view, final BindableBoolean bindableBoolean) {
        if (view.getTag(R.id.bound_observable) != bindableBoolean) {
            view.setTag(R.id.bound_observable, bindableBoolean);
            view.setOnCheckedChangeListener((group, checkedId) -> bindableBoolean.set(checkedId == group.getChildAt(1).getId()));
        }
        Boolean newValue = bindableBoolean.get();
        ((RadioButton) view.getChildAt(newValue ? 1 : 0)).setChecked(true);
    }

    @BindingAdapter("app:checked")
    public static void bindCheckbox(AppCompatCheckBox view, final BindableBoolean bindableBoolean) {
        if (view.getTag(R.id.bound_observable) != bindableBoolean) {
            view.setTag(R.id.bound_observable, bindableBoolean);
            view.setOnCheckedChangeListener((compoundButton, b) -> {
                bindableBoolean.set(b);
            });
        }
        Boolean newValue = bindableBoolean.get();
        view.setChecked(newValue);
    }

    @BindingAdapter("app:checked")
    public static void bindCheckbox(CheckBox view, final BindableBoolean bindableBoolean) {
        if (view.getTag(R.id.bound_observable) != bindableBoolean) {
            view.setTag(R.id.bound_observable, bindableBoolean);
            view.setOnCheckedChangeListener((compoundButton, b) -> bindableBoolean.set(b));
        }
        Boolean newValue = bindableBoolean.get();
        view.setChecked(newValue);
    }

    @BindingAdapter({"app:onClick"})
    public static void bindOnClick(View view, final Runnable runnable) {
        view.setOnClickListener(v -> runnable.run());
    }

    @BindingAdapter({"app:layout_constraintGuide_percent"})
    public static void bindFloatPercetageOnGuideline(View view, final float percentage) {
        ((Guideline)view).setGuidelinePercent(percentage);
    }




    @BindingAdapter("app:visibility")
    public static void bindCheckbox(LinearLayout view, final BindableBoolean bindableBoolean) {
        if (view.getTag(R.id.bound_observable) != bindableBoolean) {
            view.setTag(R.id.bound_observable, bindableBoolean);
            //view.setOnCheckedChangeListener((compoundButton, b) -> bindableBoolean.set(b));
        }
        bindableBoolean.addOnPropertyChangedCallback(new Observable.OnPropertyChangedCallback() {
            @Override
            public void onPropertyChanged(Observable sender, int propertyId) {
                view.setVisibility(bindableBoolean.get() ? View.VISIBLE : View.GONE);
            }
        });
        
        view.setVisibility(bindableBoolean.get() ? View.VISIBLE : View.GONE);
    }

}