package cpm.com.gskmtorange.utils;
import com.squareup.okhttp.ConnectionSpec;
import com.squareup.okhttp.MediaType;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.RequestBody;
import com.squareup.okhttp.Response;
import com.squareup.okhttp.TlsVersion;
import org.ksoap2.HeaderProperty;
import org.ksoap2.SoapEnvelope;
import org.ksoap2.transport.ServiceConnection;
import org.ksoap2.transport.Transport;
import org.xmlpull.v1.XmlPullParserException;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;

public class OkHttpTransportSE extends Transport {

    private final String url;
    private final OkHttpClient client;

    public OkHttpTransportSE(String url) {
        this(url, 60000); // default 60s timeout
    }

    public OkHttpTransportSE(String url, int timeout) {
        super(url, timeout);
        this.url = url;

        client = new OkHttpClient();

        // Force TLS 1.2
        ConnectionSpec spec = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
                .tlsVersions(TlsVersion.TLS_1_2,
                        TlsVersion.TLS_1_1,
                        TlsVersion.TLS_1_0)
                .build();

        client.setConnectionSpecs(Collections.singletonList(spec));
        client.setConnectTimeout(timeout, TimeUnit.MILLISECONDS);
        client.setReadTimeout(timeout, TimeUnit.MILLISECONDS);
    }

    @Override
    public List call(String soapAction, SoapEnvelope envelope, List headers)
            throws IOException, XmlPullParserException {
        return call(soapAction, envelope, headers, null);
    }


    @Override
    public ServiceConnection getServiceConnection() throws IOException {
        return null; // not used with OkHttp
    }

    @Override
    public List<HeaderProperty> call(String soapAction, SoapEnvelope envelope, List headers, File outputFile)
            throws IOException, XmlPullParserException {

        if (soapAction == null) {
            soapAction = "";
        }

        byte[] requestData = this.createRequestData(envelope, "UTF-8");
        this.requestDump = this.debug ? new String(requestData) : null;
        this.responseDump = null;

        // Build request
        Request.Builder builder = new Request.Builder()
                .url(url)
                .addHeader("User-Agent", "ksoap2-android/2.6.0+");

        if (envelope.version == SoapEnvelope.VER12) {
            builder.addHeader("Content-Type", "application/soap+xml;charset=utf-8");
        } else {
            builder.addHeader("Content-Type", "text/xml;charset=utf-8");
            builder.addHeader("SOAPAction", soapAction); // Match HttpTransportSE
        }

        // Add custom headers if any
        if (headers != null) {
            for (Object h : headers) {
                HeaderProperty hp = (HeaderProperty) h;
                if (hp.getKey() != null && hp.getValue() != null) {
                    builder.addHeader(hp.getKey(), hp.getValue());
                }
            }
        }

        builder.post(RequestBody.create(MediaType.parse("text/xml; charset=utf-8"), requestData));

        // Execute request
        Response response = client.newCall(builder.build()).execute();

        if (!response.isSuccessful()) {
            throw new IOException("HTTP request failed, code: " + response.code());
        }

        // Collect response headers
        List<HeaderProperty> retHeaders = new ArrayList<>();
        for (String name : response.headers().names()) {
            retHeaders.add(new HeaderProperty(name, response.header(name)));
        }
        // Parse SOAP response
        parseResponse(envelope, response.body().byteStream());
        return retHeaders;
    }
}
