package com.openxc.enabler;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;

import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;
import androidx.fragment.app.ListFragment;
import com.openxc.VehicleManager;
import com.openxc.messages.DiagnosticRequest;
import com.openxc.messages.DiagnosticResponse;
import com.openxc.messages.VehicleMessage;
import com.openxcplatform.enabler.R;

public class DiagnosticRequestFragment extends ListFragment {
    private final static String DiagnosticMessage = "DiagnosticRequestFragment";

    private VehicleManager mVehicleManager;
    private DiagnosticResponseAdapter diagnosticResponseAdapter;
    private View mLastRequestView;

    private VehicleMessage.Listener mListener = new VehicleMessage.Listener() {
        @Override
        public void receive(final VehicleMessage message) {
            if (((OpenXcEnablerActivity)getActivity()).isDTCScanning()) {
                return;
            }
            Activity activity = getActivity();
            if(activity != null) {
                getActivity().runOnUiThread(new Runnable() {
                    public void run() {
                        diagnosticResponseAdapter.add(message.asDiagnosticResponse());
                    }
                });
            }
        }
    };

    private ServiceConnection mConnection = new ServiceConnection() {
        public void onServiceConnected(ComponentName className,
                IBinder service) {
            Log.i(DiagnosticMessage, "Bound to VehicleManager");
            mVehicleManager = ((VehicleManager.VehicleBinder)service
                    ).getService();

            mVehicleManager.addListener(DiagnosticResponse.class, mListener);
        }

        public void onServiceDisconnected(ComponentName className) {
            Log.w(DiagnosticMessage, "VehicleService disconnected unexpectedly");
            mVehicleManager = null;
        }
    };

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        diagnosticResponseAdapter = new DiagnosticResponseAdapter(getActivity());
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        final View v = inflater.inflate(R.layout.diagnostic_request_fragment,
                container, false);

        final Spinner spinner = (Spinner) v.findViewById(R.id.bus_spinner);
        // Create an ArrayAdapter using the string array and a default spinner
        // layout
        ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(
                getActivity(), R.array.buses_array
                , android.R.layout.simple_spinner_item);
        // Specify the layout to use when the list of choices appears
        adapter.setDropDownViewResource(
                android.R.layout.simple_spinner_dropdown_item);
        // Apply the adapter to the spinner
        spinner.setAdapter(adapter);

        Button btn = (Button) v.findViewById(R.id.send_request);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View buttonView) {
                onSendDiagnosticRequest(spinner,
                        (EditText) v.findViewById(R.id.diag_request_id),
                        (EditText) v.findViewById(R.id.diag_request_mode),
                        (EditText) v.findViewById(R.id.diag_request_pid));
            }
        });

        mLastRequestView = v.findViewById(R.id.last_request);
        return v;
    }

    private void onSendDiagnosticRequest(Spinner busSpinner,
            EditText idView, EditText modeView, EditText pidView) {
        boolean validInput = true;
        if(idView.getText().toString().isEmpty()) {
            idView.setError("ID is required");
            validInput = false;
        }

        if(modeView.getText().toString().isEmpty()) {
            modeView.setError("Mode is required");
            validInput = false;
        }

        if(validInput) {
            DiagnosticRequest request = new DiagnosticRequest(
                    Integer.valueOf(busSpinner.getSelectedItem().toString()),
                    Integer.valueOf(idView.getText().toString(), 16),
                    Integer.valueOf(modeView.getText().toString(), 16));
            // Make sure to update after sending so the timestamp is set by the
            // VehicleManager
            String pidString = pidView.getText().toString();
            if(!pidString.isEmpty()) {
                request.setPid(Integer.valueOf(pidString, 16));
            }
            mVehicleManager.send(request);
            // Make sure to update after sending so the timestamp is set by the
            // VehicleManager
            updateLastRequestView(request);
        } else {
            Log.i(DiagnosticMessage, "Form is invalid, not sending diagnostic request");
        }
    }

    private void updateLastRequestView(final DiagnosticRequest request) {
        getActivity().runOnUiThread(new Runnable() {
            public void run() {
                // This is duplicated in DiagnosticResponseAdapter - figure
                // out the best way to share this rendering info
                TextView timestampView = (TextView)
                        mLastRequestView.findViewById(R.id.timestamp);
                timestampView.setText(VehicleMessageAdapter.formatTimestamp(
                            request));

                TextView busView = (TextView)
                        mLastRequestView.findViewById(R.id.bus);
                busView.setText("" + request.getBusId());

                TextView idView = (TextView)
                        mLastRequestView.findViewById(R.id.id);
                idView.setText("0x" + Integer.toHexString(request.getId()));

                TextView modeView = (TextView)
                        mLastRequestView.findViewById(R.id.mode);
                modeView.setText("0x" + Integer.toHexString(request.getMode()));

                if(request.hasPid()) {
                    TextView pidView = (TextView)
                            mLastRequestView.findViewById(R.id.pid);
                    pidView.setText("0x" + Integer.toHexString(
                                request.getPid()));
                }
            }
        });
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        setListAdapter(diagnosticResponseAdapter);
    }

    @Override
    public void onResume() {
        super.onResume();
        if (getActivity() != null) {
            getActivity().bindService(
                    new Intent(getActivity(), VehicleManager.class),
                    mConnection, Context.BIND_AUTO_CREATE);
        }
    }

    @Override
    public void onPause() {
        super.onPause();
        if(mVehicleManager != null) {
            Log.i(DiagnosticMessage, "Unbinding from vehicle service");
            mVehicleManager.removeListener(DiagnosticResponse.class, mListener);
            getActivity().unbindService(mConnection);
            mVehicleManager = null;
        }
    }
}
