using Android.Content;
using Android.Graphics.Drawables;
using Android.Views;
using Android.Widget;
using Billing.Droid.Renderers;
using Billing.UI;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
using RadioButton = Android.Widget.RadioButton;

[assembly: ExportRenderer(typeof(SegmentedControl), typeof(SegmentedControlRenderer))]
namespace Billing.Droid.Renderers
{
    public class SegmentedControlRenderer : ViewRenderer<SegmentedControl, RadioGroup>
    {
        RadioGroup nativeControl;
        RadioButton _rb;
        readonly Context context;

        public SegmentedControlRenderer(Context context) : base(context)
        {
            this.context = context;
        }

        protected override void OnElementChanged(ElementChangedEventArgs<SegmentedControl> e)
        {
            base.OnElementChanged(e);

            if (Control == null)
            {
                // Instantiate the native control and assign it to the Control property with
                // the SetNativeControl method
                var layoutInflater = LayoutInflater.From(context);

                var view = layoutInflater.Inflate(Resource.Layout.RadioGroup, null);

                nativeControl = (RadioGroup)layoutInflater.Inflate(Resource.Layout.RadioGroup, null);
                var density = context.Resources.DisplayMetrics.Density;

                for (var i = 0; i < Element.Children.Count; i++)
                {
                    var o = Element.Children[i];
                    var rb = (RadioButton)layoutInflater.Inflate(Resource.Layout.RadioButton, null);

                    var width = rb.Paint.MeasureText(o.Text) * density + 0.5f;
                    rb.LayoutParameters = new RadioGroup.LayoutParams((int)width, LayoutParams.WrapContent, 1f);
                    rb.Text = o.Text;

                    if (i == 0)
                        rb.SetBackgroundResource(Resource.Drawable.segmented_control_first_background);
                    else if (i == Element.Children.Count - 1)
                        rb.SetBackgroundResource(Resource.Drawable.segmented_control_last_background);
                    else
                        rb.SetBackgroundResource(Resource.Drawable.segmented_control_background);

                    ConfigureRadioButton(i, rb);

                    nativeControl.AddView(rb);
                }

                var option = (RadioButton)nativeControl.GetChildAt(Element.SelectedSegmentIndex);

                if (option != null)
                    option.Checked = true;

                SetNativeControl(nativeControl);
            }

            if (e.OldElement != null)
            {
                // Unsubscribe from event handlers and cleanup any resources
                if (nativeControl != null)
                    nativeControl.CheckedChange -= NativeControl_ValueChanged;
            }

            if (e.NewElement != null)
            {
                // Configure the control and subscribe to event handlers
                nativeControl.CheckedChange += NativeControl_ValueChanged;
            }
        }

        protected override void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            base.OnElementPropertyChanged(sender, e);

            if (nativeControl == null || Element == null) return;

            switch (e.PropertyName)
            {
                case "Renderer":
                    Element?.SendValueChanged();
                    break;
                case nameof(SegmentedControl.SelectedSegmentIndex):
                    var option = (RadioButton)nativeControl.GetChildAt(Element.SelectedSegmentIndex);

                    if (option != null)
                        option.Checked = true;

                    if (Element.SelectedSegmentIndex < 0)
                    {
                        var layoutInflater = LayoutInflater.From(context);

                        nativeControl = (RadioGroup)layoutInflater.Inflate(Resource.Layout.RadioGroup, null);

                        for (var i = 0; i < Element.Children.Count; i++)
                        {
                            var o = Element.Children[i];
                            var rb = (RadioButton)layoutInflater.Inflate(Resource.Layout.RadioButton, null);

                            var width = rb.Paint.MeasureText(o.Text);
                            rb.LayoutParameters = new RadioGroup.LayoutParams((int)width, LayoutParams.WrapContent, 1f);
                            rb.Text = o.Text;

                            if (i == 0)
                                rb.SetBackgroundResource(Resource.Drawable.segmented_control_first_background);
                            else if (i == Element.Children.Count - 1)
                                rb.SetBackgroundResource(Resource.Drawable.segmented_control_last_background);
                            else
                                rb.SetBackgroundResource(Resource.Drawable.segmented_control_background);

                            ConfigureRadioButton(i, rb);

                            nativeControl.AddView(rb);
                        }

                        nativeControl.CheckedChange += NativeControl_ValueChanged;

                        SetNativeControl(nativeControl);
                    }

                    Element.SendValueChanged();
                    break;
                case nameof(SegmentedControl.TintColor):
                    OnPropertyChanged();
                    break;
                case nameof(SegmentedControl.IsEnabled):
                    OnPropertyChanged();
                    break;
                case nameof(SegmentedControl.SelectedTextColor):
                    var v = (RadioButton)nativeControl.GetChildAt(Element.SelectedSegmentIndex);
                    v.SetTextColor(Element.SelectedTextColor.ToAndroid());
                    break;
            }
        }

        void OnPropertyChanged()
        {
            if (nativeControl != null && Element != null)
            {
                for (var i = 0; i < Element.Children.Count; i++)
                {
                    var rb = (RadioButton)nativeControl.GetChildAt(i);

                    ConfigureRadioButton(i, rb);
                }
            }
        }

        void ConfigureRadioButton(int i, RadioButton rb)
        {
            var textColor = Element.SelectedTextColor;
            if (i == Element.SelectedSegmentIndex)
            {
                rb.SetTextColor(textColor.ToAndroid());
                rb.Paint.FakeBoldText = true;
                _rb = rb;
            }
            else
            {
                var tColor = Element.IsEnabled ?
                    textColor.IsDefault ? Element.TintColor.ToAndroid() : textColor.MultiplyAlpha(.6).ToAndroid() :
                    Element.DisabledColor.ToAndroid();
                rb.SetTextColor(tColor);
            }

            GradientDrawable selectedShape;
            GradientDrawable unselectedShape;

            var gradientDrawable = (StateListDrawable)rb.Background;
            var drawableContainerState = (DrawableContainer.DrawableContainerState)gradientDrawable.GetConstantState();
            var children = drawableContainerState.GetChildren();

            // Doesnt works on API < 18
            selectedShape = children[0] is GradientDrawable selected ? selected : (GradientDrawable)((InsetDrawable)children[0]).Drawable;
            unselectedShape = children[1] is GradientDrawable unselected ? unselected : (GradientDrawable)((InsetDrawable)children[1]).Drawable;

            var color = Element.IsEnabled ? Element.TintColor.ToAndroid() : Element.DisabledColor.ToAndroid();

            selectedShape.SetStroke(3, color);
            selectedShape.SetColor(color);
            unselectedShape.SetStroke(3, color);

            rb.Enabled = Element.IsEnabled;
        }

        void NativeControl_ValueChanged(object sender, RadioGroup.CheckedChangeEventArgs e)
        {
            var rg = (RadioGroup)sender;
            if (rg.CheckedRadioButtonId != -1)
            {
                var id = rg.CheckedRadioButtonId;
                var radioButton = rg.FindViewById(id);
                var radioId = rg.IndexOfChild(radioButton);

                var rb = (RadioButton)rg.GetChildAt(radioId);

                var textColor = Element.SelectedTextColor;
                var color = Element.IsEnabled ?
                    textColor.IsDefault ? Element.TintColor.ToAndroid() : textColor.MultiplyAlpha(.6).ToAndroid() :
                    Element.DisabledColor.ToAndroid();
                if (_rb != null)
                {
                    _rb.SetTextColor(color);
                    _rb.Paint.FakeBoldText = false;
                }
                rb.SetTextColor(Element.SelectedTextColor.ToAndroid());
                rb.Paint.FakeBoldText = true;
                _rb = rb;

                Element.SelectedSegmentIndex = radioId;
            }
        }

        protected override void Dispose(bool disposing)
        {
            if (nativeControl != null)
            {
                nativeControl.CheckedChange -= NativeControl_ValueChanged;
                nativeControl.Dispose();
                nativeControl = null;
                _rb = null;
            }

            try
            {
                base.Dispose(disposing);
            }
            catch
            {
                return;
            }
        }
    }
}
