package lingquan.firstApp.placesearch.fragment;

import android.Manifest;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.PackageManager;
import android.location.Location;
import android.os.Bundle;
import android.os.Looper;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.Fragment;
import android.support.v4.widget.CircularProgressDrawable;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.widget.AdapterView;
import android.widget.AutoCompleteTextView;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;
import com.google.android.gms.common.GooglePlayServicesNotAvailableException;
import com.google.android.gms.common.GooglePlayServicesRepairableException;
import com.google.android.gms.common.api.ApiException;
import com.google.android.gms.common.api.ResolvableApiException;
import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationCallback;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationResult;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.location.LocationSettingsRequest;
import com.google.android.gms.location.LocationSettingsResponse;
import com.google.android.gms.location.LocationSettingsStatusCodes;
import com.google.android.gms.location.SettingsClient;
import com.google.android.gms.location.places.Place;
import com.google.android.gms.location.places.ui.PlaceAutocomplete;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.gms.tasks.Task;
import com.google.gson.Gson;

import java.text.DateFormat;
import java.util.Date;

import lingquan.firstApp.placesearch.R;
import lingquan.firstApp.placesearch.Utils.BaseUrl;
import lingquan.firstApp.placesearch.Utils.Utils;
import lingquan.firstApp.placesearch.activity.PlacesSearchResultActivtity;
import lingquan.firstApp.placesearch.adapter.CustomAutoCompleteAdapter;
import lingquan.firstApp.placesearch.jsonscn.json2bean.JsonsRootBean;
import lingquan.firstApp.placesearch.obj.PlacesSearchResultObj;



public class PlaceSearchFragment extends Fragment implements CompoundButton.OnCheckedChangeListener, View.OnClickListener, TextWatcher, RadioGroup.OnCheckedChangeListener {


//    public static String Latitude = "151.1957362";
//    public static String Longitude = "-33.8670522";
    public static String Latitude ;
    public static String Longitude ;
    private static final long UPDATE_INTERVAL_IN_MILLISECONDS = 10000;
    private static final long FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS =
            UPDATE_INTERVAL_IN_MILLISECONDS / 2;
    private static final String TAG = PlaceSearchFragment.class.getSimpleName();
    private static final int REQUEST_PERMISSIONS_REQUEST_CODE = 34;
    private static final int REQUEST_CHECK_SETTINGS = 0x1;
    private Context context;
    private EditText mPlaceSearchKeyWord;
    private Spinner mPlaceSearchCategory;
    private EditText mPlaceSearchDistance;
    private RadioButton mPlaceSearchCurrentLocation;
    private RadioButton mPlaceSearchOtherLocation;
    private AutoCompleteTextView mPlaceSearchLocation;
    private RadioGroup group;
    private Button mPlaceSearchSubmit;
    private Button mPlaceSearchClear;
    private FusedLocationProviderClient mFusedLocationClient;
    private String mLastUpdateTime;
    private Location mCurrentLocation;
    private String category = "Default";
    private String formatted_category;
    private ProgressDialog dialog;
    private String oldLocation;
    private CustomAutoCompleteAdapter adapter;
    private TextView keywordReminder;
    private TextView locationReminder;
    private String[] latlng;


    /**
     * Provides access to the Location Settings API.
     */
    private SettingsClient mSettingsClient;

    /**
     * Stores parameters for requests to the FusedLocationProviderApi.
     */
    private LocationRequest mLocationRequest;

    /**
     * Stores the types of location services the client is interested in using. Used for checking
     * settings to determine if the device has optimal location settings.
     */
    private LocationSettingsRequest mLocationSettingsRequest;

    /**
     * Callback for Location events.
     */
    private LocationCallback mLocationCallback;
    private boolean mRequestingLocationUpdates;
    private int AUTO_COMP_REQ_CODE = 0x01;
    private JsonsRootBean obj;

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        dialog = new ProgressDialog(context);
        dialog.setCancelable(false);
        dialog.setIndeterminate(true);
        dialog.setMessage("Fetching Results");
        dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
        this.context = context;
        mFusedLocationClient = LocationServices.getFusedLocationProviderClient(context);
        mSettingsClient = LocationServices.getSettingsClient(context);
        adapter = new CustomAutoCompleteAdapter(context);
        createLocationCallback();
        createLocationRequest();
        buildLocationSettingsRequest();
    }

    private void buildLocationSettingsRequest() {
        LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
        builder.addLocationRequest(mLocationRequest);
        mLocationSettingsRequest = builder.build();
    }

    private void createLocationRequest() {
        mLocationRequest = new LocationRequest();
        mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
        mLocationRequest.setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == REQUEST_PERMISSIONS_REQUEST_CODE) {
            if (grantResults.length <= 0) {
                Log.i(TAG, "User interaction was cancelled.");
            } else if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                if (mRequestingLocationUpdates) {
                    Log.i(TAG, "Permission granted, updates requested, starting location updates");
                    startLocationUpdates();
                }
            } else {
                // Permission denied.
            }
        }
    }

    private void createLocationCallback() {
        mLocationCallback = new LocationCallback() {
            @Override
            public void onLocationResult(LocationResult locationResult) {
                super.onLocationResult(locationResult);
                mCurrentLocation = locationResult.getLastLocation();
                Log.e("lingquan", "the current location is " + mCurrentLocation);
                mLastUpdateTime = DateFormat.getTimeInstance().format(new Date());
                updateLocationUI();
            }
        };
    }

    private void requestPermissions() {
        boolean shouldProvideRationale =
                ActivityCompat.shouldShowRequestPermissionRationale((Activity) context,
                        Manifest.permission.ACCESS_FINE_LOCATION);
        requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                REQUEST_PERMISSIONS_REQUEST_CODE);
    }

    private void startLocationUpdates() {
        mRequestingLocationUpdates = true;
        mSettingsClient.checkLocationSettings(mLocationSettingsRequest)
                .addOnSuccessListener((Activity) context, new OnSuccessListener<LocationSettingsResponse>() {
                    @Override
                    public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
                        Log.i(TAG, "All location settings are satisfied.");
                        if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                            requestPermissions();
                            return;
                        }
                        mFusedLocationClient.requestLocationUpdates(mLocationRequest,
                                mLocationCallback, Looper.myLooper());
                    }
                })
                .addOnFailureListener((Activity) context, new OnFailureListener() {
                    @Override
                    public void onFailure(@NonNull Exception e) {
                        int statusCode = ((ApiException) e).getStatusCode();
                        switch (statusCode) {
                            case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
                                Log.i(TAG, "Location settings are not satisfied. Attempting to upgrade " +
                                        "location settings ");
                                try {
                                    ResolvableApiException rae = (ResolvableApiException) e;
                                    rae.startResolutionForResult((Activity) context, REQUEST_CHECK_SETTINGS);
                                } catch (IntentSender.SendIntentException sie) {
                                    Log.i(TAG, "PendingIntent unable to execute request.");
                                }
                                break;
                            case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
                                String errorMessage = "Location settings are inadequate, and cannot be " +
                                        "fixed here. Fix in Settings.";
                                Log.e(TAG, errorMessage);
                                Toast.makeText(context, errorMessage, Toast.LENGTH_LONG).show();
                                mRequestingLocationUpdates = false;
                        }
                    }
                });
    }

    private void updateLocationUI() {
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View convertView = inflater.inflate(R.layout.places_search_fragment, container, false);
        mPlaceSearchKeyWord = convertView.findViewById(R.id.search_places_keyword);
        mPlaceSearchCategory = convertView.findViewById(R.id.spinner);
        mPlaceSearchDistance = convertView.findViewById(R.id.place_search_distances);
        mPlaceSearchCurrentLocation = convertView.findViewById(R.id.current_location);
        mPlaceSearchOtherLocation = convertView.findViewById(R.id.other_location);
        mPlaceSearchLocation = convertView.findViewById(R.id.place_search_location);
        mPlaceSearchSubmit = convertView.findViewById(R.id.place_search_submit);
        mPlaceSearchClear = convertView.findViewById(R.id.place_search_clear);
        group = convertView.findViewById(R.id.group);
        keywordReminder = convertView.findViewById(R.id.reminder_keyword);
        locationReminder = convertView.findViewById(R.id.reminder_loaction);
        keywordReminder.setVisibility(View.GONE);
        locationReminder.setVisibility(View.GONE);
        group.setOnCheckedChangeListener(this);
        group.check(R.id.current_location);
        mPlaceSearchKeyWord.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

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

            }

            @Override
            public void afterTextChanged(Editable s) {
                if (TextUtils.isEmpty(s.toString())){
                } else {
                    keywordReminder.setVisibility(View.GONE);
                }
            }
        });

        mPlaceSearchLocation.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

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

            }

            @Override
            public void afterTextChanged(Editable s) {
                if (TextUtils.isEmpty(s.toString())){
                } else {
                    locationReminder.setVisibility(View.GONE);
                }
            }
        });

        mPlaceSearchLocation.setAdapter(adapter);
        mPlaceSearchLocation.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                obj = null;
                final StringBuffer buffer = new StringBuffer();
                buffer.append(BaseUrl.Geocoding_URL);
                String text = mPlaceSearchLocation.getText().toString();
                text.replaceAll(" ", "+");
                buffer.append(text);
                Log.v("latlng url:",buffer.toString());

                RequestQueue mQueue = Volley.newRequestQueue(context);
                StringRequest request = new StringRequest(Request.Method.GET, buffer.toString(), new Response.Listener<String>() {
                    @Override
                    public void onResponse(String response) {
                        Log.v("latlng res:",response);
                        latlng = response.substring(1,response.length() - 1).split(",");
                        Latitude = latlng[0];
                        Longitude = latlng[1];
                        Log.v("latlng is:",Latitude+","+Longitude);

                    }
                }, new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                        dialog.dismiss();
                    }
                });
                mQueue.add(request);
            }
        });
        mPlaceSearchSubmit.setOnClickListener(this);
        mPlaceSearchClear.setOnClickListener(this);
        mPlaceSearchCategory.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                category = (String) parent.getAdapter().getItem(position);

                category = category.toLowerCase();
                formatted_category = category.replaceAll(" ","_");


            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {

            }
        });
        return convertView;
    }

    private void stopLocationUpdates() {
        if (!mRequestingLocationUpdates) {
            Log.d(TAG, "stopLocationUpdates: updates never requested, no-op.");
            return;
        }

        mFusedLocationClient.removeLocationUpdates(mLocationCallback)
                .addOnCompleteListener((Activity) context, new OnCompleteListener<Void>() {
                    @Override
                    public void onComplete(@NonNull Task<Void> task) {
                        mRequestingLocationUpdates = false;
                    }
                });
    }

    @Override
    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
        if (buttonView == mPlaceSearchCurrentLocation) {
            if (isChecked) {
                mPlaceSearchOtherLocation.setChecked(false);
                mRequestingLocationUpdates = true;
                startLocationUpdates();
            }
        } else if (buttonView == mPlaceSearchOtherLocation) {
            if (isChecked) mPlaceSearchCurrentLocation.setChecked(false);
        }
    }

    @Override
    public void onClick(View v) {
        if (v == mPlaceSearchSubmit) {
            String text = mPlaceSearchKeyWord.getText().toString().replaceAll(" ","");
            Log.v("text-->",text);

            if ((TextUtils.isEmpty(mPlaceSearchKeyWord.getText())||text.length() == 0) && mPlaceSearchOtherLocation.isChecked()) {
                Log.v("two","here");
                keywordReminder.setVisibility(View.VISIBLE);
                locationReminder.setVisibility(View.VISIBLE);
                Toast.makeText(context, "please fix all fields with errors", Toast.LENGTH_LONG).show();
                return;
            }
            keywordReminder.setVisibility(View.GONE);
            locationReminder.setVisibility(View.GONE);




            if (TextUtils.isEmpty(mPlaceSearchKeyWord.getText())||text.length() == 0  && mPlaceSearchCurrentLocation.isChecked()) {
                Log.v("one","here");
                keywordReminder.setVisibility(View.VISIBLE);
                Toast.makeText(context, "please fix all fields with errors", Toast.LENGTH_LONG).show();
                return;
            }
            keywordReminder.setVisibility(View.GONE);



            if (mPlaceSearchCurrentLocation.isChecked()) {
                if (mCurrentLocation == null) {
                    Toast.makeText(context, "can not find the current places,wait a minutes..", Toast.LENGTH_LONG).show();
                    return;
                }
                Latitude = String.valueOf(mCurrentLocation.getLatitude());
                Longitude = String.valueOf(mCurrentLocation.getLongitude());
            } else if (mPlaceSearchOtherLocation.isChecked()) {
                if (TextUtils.isEmpty(mPlaceSearchLocation.getText())) {
                    locationReminder.setVisibility(View.VISIBLE);
                    Toast.makeText(context, "please fix all fields with errors", Toast.LENGTH_LONG).show();
                    return;
                }
                locationReminder.setVisibility(View.GONE);
                if (latlng == null) {
                    Toast.makeText(context, "can not find the  places position,wait a minutes..", Toast.LENGTH_LONG).show();
                    return;
                }
            }
            searchPlaces();

        } else if (v == mPlaceSearchClear) {
            clearSearchPlace();
        }
    }

    private void clearSearchPlace() {
        mPlaceSearchKeyWord.setText("");
        mPlaceSearchCategory.setSelection(0);
        mPlaceSearchCurrentLocation.setChecked(true);
        mPlaceSearchOtherLocation.setChecked(false);
        mPlaceSearchDistance.setText("");
        mPlaceSearchLocation.setText("");
        keywordReminder.setVisibility(View.GONE);
        locationReminder.setVisibility(View.GONE);
    }

    private void searchPlaces() {
        dialog.show();
        final StringBuffer buffer = new StringBuffer();
        buffer.append(BaseUrl.SEARCH_URL);
//        buffer.append("http://127.0.0.1:8080/");

        buffer.append("startLng=").append(Longitude);
        buffer.append("&");
        buffer.append("startLat=").append(Latitude);
        buffer.append("&");
        if (!TextUtils.isEmpty(mPlaceSearchDistance.getText())) {
            buffer.append("distance=").append(mPlaceSearchDistance.getText()).append("&");
        } else {
            buffer.append("distance=").append(10).append("&");
        }

        buffer.append("category=").append(formatted_category).append("&keyword=").append(mPlaceSearchKeyWord.getText());
        Log.v("request url",buffer.toString());

        RequestQueue mQueue = Volley.newRequestQueue(context);
        StringRequest request = new StringRequest(Request.Method.GET, buffer.toString(), new Response.Listener<String>() {
            @Override
            public void onResponse(String response) {
                dialog.dismiss();
                PlacesSearchResultObj obj = new Gson().fromJson(response, PlacesSearchResultObj.class);
                Intent intent = new Intent(context, PlacesSearchResultActivtity.class);
                intent.putExtra("data", obj);
                intent.putExtra("url", buffer.toString());
                startActivity(intent);
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                dialog.dismiss();
                Toast.makeText(getContext(),"No network",Toast.LENGTH_LONG).show();
            }
        });
        mQueue.add(request);
    }

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

    }

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

    }

    @Override
    public void afterTextChanged(Editable s) {
        String location = s.toString();
        if (TextUtils.isEmpty(location)) return;
        if (location.equals(oldLocation)) return;
        try {
            Intent build = new PlaceAutocomplete.IntentBuilder(PlaceAutocomplete.MODE_FULLSCREEN).zzh(s.toString()).
                    build((Activity) context);
            startActivityForResult(build, AUTO_COMP_REQ_CODE);
        } catch (GooglePlayServicesRepairableException e) {
            e.printStackTrace();
        } catch (GooglePlayServicesNotAvailableException e) {
            e.printStackTrace();
        }
        oldLocation = location;
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == Activity.RESULT_OK) {
            Place place = PlaceAutocomplete.getPlace(context, data);
            Log.e("lingquan", "the task is " + resultCode + " " + requestCode + "     " + PlaceAutocomplete.getPlace(context, data).toString());
            oldLocation = place.getAddress().toString();
            mPlaceSearchLocation.setText(place.getAddress());
        }
    }

    @Override
    public void onCheckedChanged(RadioGroup group, int checkedId) {
        if (checkedId == R.id.current_location){
            mPlaceSearchLocation.setText("");
            Log.v("try to clear location",mPlaceSearchLocation.getText().toString());
            mRequestingLocationUpdates = true;
            startLocationUpdates();
            locationReminder.setVisibility(View.GONE);
            mPlaceSearchLocation.setInputType(EditorInfo.TYPE_NULL);
        }else if (checkedId==R.id.other_location){
            mPlaceSearchLocation.setInputType(EditorInfo.TYPE_CLASS_TEXT);
        }
    }
}