package com.example.epl498_labs.ui.apiCall;

import android.os.Bundle;
import androidx.fragment.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.Spinner;
import com.example.epl498_labs.R;
import android.widget.TextView;

import com.example.epl498_labs.databinding.FragmentApiCallBinding;
import com.squareup.picasso.Picasso;

import org.chromium.net.CronetEngine;
import org.chromium.net.CronetException;
import org.chromium.net.UrlRequest;
import org.chromium.net.UrlResponseInfo;
import org.json.JSONException;
import org.json.JSONObject;

import java.nio.ByteBuffer;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

/**
 * This class is responsible for making an api call to open weather rest api and display the
 * temperature and condition on the screen depending on the city of Cyprus that the user has selected
 */
public class ApiCallFragment extends Fragment {

    private CronetEngine.Builder myBuilder;
    private CronetEngine cronetEngine;
    private Executor executor;
    private TextView weatherTxt;
    private TextView cityTxt;
    private ImageView weatherIcon;
    private ProgressBar progressBar;
    private Spinner citySpinner;
    private String selectedCity;

    private FragmentApiCallBinding binding;

    @Override
    public View onCreateView(
            LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState
    ) {
        // Inflate the binding for this fragment
        binding = FragmentApiCallBinding.inflate(inflater, container, false);
        weatherTxt = binding.weatherTxt;
        cityTxt = binding.cityTxt;
        weatherIcon = binding.imageView;
        progressBar = binding.progressBar;
        citySpinner = binding.dropdownCity;

        // Create a spinner with city options
        // !! The cities_array is defined inside res > values > strings.xml
        String[] cities = getResources().getStringArray(R.array.cities_array);
        ArrayAdapter<String> adapter = new ArrayAdapter<>(getActivity(), android.R.layout.simple_spinner_dropdown_item, cities);
        citySpinner.setAdapter(adapter);
        // here we define that the first selected city will be the first from our array
        selectedCity = citySpinner.getItemAtPosition(0).toString();

        // TODO 0: using .setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {})
        //  update the selectedCity whenever a user chooses a new city (from the spinner)


        // TODO 1: using .setOnClickListener call the make makeWeatherApiRequest method every time
        //  the button get weather is clicked

        // TODO 3: get the weather as soon as the view of our fragment has been created
        
        
        return binding.getRoot();
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        myBuilder = new CronetEngine.Builder(getContext());
        cronetEngine = myBuilder.build();
        executor = Executors.newSingleThreadExecutor();
    }

    private void makeWeatherApiRequest() {
        // TODO 4: When making the request we want to hide the previous weather icon, weather text
        //  and city text (you can do this using the .setVisibility(View.GONE)

        // TODO 5: make the progress bar visible again

        // TODO 6: go to the slides of our lab and see how to create an api builder
        //  don't forget to change the url so that it can get the selectedCity every time



        UrlRequest request = requestBuilder.build();
        // here we make the actual api call
        request.start();
    }

    private void updateWeatherTextView(String weatherData) {
        /**
         * UI components can only be accessed and modified from the main thread.
         * Since API calls are asynchronous and may execute on background threads,
         * we use runOnUiThread to safely update the TextView with the weather data
         * on the main thread, ensuring a smooth user experience.
         */
        getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {
                try {
                    JSONObject jsonObject = new JSONObject(weatherData);
                    JSONObject current = jsonObject.getJSONObject("current");

                    // TODO 8: get temperature
                    String temperatureC = "";
                    // TODO 9: get condition
                    String conditionText = "";
                    // TODO 10: get icon
                    String iconUrl = "";

                    // TODO 11: Update the TextView with temperature and condition text (use the .setText() method)

                    // TODO 12: Update the cityTxt's text to display the selected City

                    // We use picasso to load the icon that the response returned
                    Picasso.get().load("https:" + iconUrl).resize(300, 300).into(weatherIcon);

                    // TODO 13: now let's make the progress bar invisible again
                    //   and make the weather icon, weather text and city text visible again

                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * This inner class is responsible to extend the url request callback and override the
     * appropriate methods according to the implementation we want to setup
     */
    class EPL498RequestCallback extends UrlRequest.Callback {
        private static final String TAG = "EPL498RequestCallback";

        @Override
        public void onResponseStarted(UrlRequest request, UrlResponseInfo info) {
            Log.i(TAG, "onResponseStarted method called.");
            // You should call the request.read() method before the request can be
            // further processed. The following instruction provides a ByteBuffer object
            // with a capacity of 102400 bytes for the read() method. The same buffer
            // with data is passed to the onReadCompleted() method.
            request.read(ByteBuffer.allocateDirect(102400));
        }

        @Override
        public void onReadCompleted(UrlRequest request, UrlResponseInfo info, ByteBuffer byteBuffer) {
            Log.i(TAG, "onReadCompleted method called.");
            // You should keep reading the request until there's no more data.
            byteBuffer.flip();
            byte[] bytes = new byte[byteBuffer.remaining()];
            byteBuffer.get(bytes);
            String response = new String(bytes);

            // TODO 7: print the json result in Logcat
            //   Then run the application, and go in Logcat to see the result

            updateWeatherTextView(response);

            byteBuffer.clear();
            request.read(byteBuffer);
        }

        @Override
        public void onSucceeded(UrlRequest request, UrlResponseInfo info) {
            Log.i(TAG, "onSucceeded method called.");
        }

        @Override
        public void onFailed(UrlRequest request, UrlResponseInfo info, CronetException error) {
            Log.i(TAG, "onFailed method called.");
        }

        @Override
        public void onRedirectReceived(UrlRequest request, UrlResponseInfo info, String newLocationUrl) throws Exception {
            // do nothing for now
        }
    }
}

