package ru.yandex.webmaster.common.tvm;

import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;

import javax.net.ssl.SSLContext;

import org.apache.commons.io.IOUtils;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.AllowAllHostnameVerifier;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.ssl.SSLContextBuilder;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Required;

import ru.yandex.passport.tvmauth.deprecated.ServiceContext;
import ru.yandex.wmtools.common.service.AbstractExternalHttpService;

/**
 * Created by aleksart on 26.06.17.
 */
public class Tvm2TokenService extends AbstractExternalHttpService {

    private final static Logger log = LoggerFactory.getLogger(Tvm2TokenService.class);
    private int clientId;
    private String destinationClientId;
    private String grantType;
    private String secret;
    private TVM2RequestService tvm2RequestService;
    private ServiceContext serviceContext;

    @Required
    public void setDestinationClientId(String destinationClientId) {
        this.destinationClientId = destinationClientId;
    }

    @Required
    public void setClientId(int clientId) {
        this.clientId = clientId;
    }


    @Required
    public void setGrantType(String grantType) {
        this.grantType = grantType;
    }

    @Required
    public void setSecret(String secret) {
        this.secret = secret;
    }

    @Required
    public void setTvm2RequestService(TVM2RequestService tvm2RequestService) {
        this.tvm2RequestService = tvm2RequestService;
    }

    public void init() {
        serviceContext = new ServiceContext(clientId, secret, tvm2RequestService.getTvmKeys());
    }


    public String getToken()  {
        try {

            SSLContext sslContext = null;

            sslContext = new SSLContextBuilder().loadTrustMaterial(null, (arg0, arg1) -> true).build();

            CloseableHttpClient client = HttpClientBuilder.create()
                    .setHostnameVerifier(new AllowAllHostnameVerifier())
                    .setSslcontext(sslContext).build();


            HttpPost postRequest = new HttpPost(externalServantUrl + "/2/ticket");
            List<NameValuePair> postParameters = new ArrayList<>();
            postParameters.add(new BasicNameValuePair("src", String.valueOf(clientId)));
            postParameters.add(new BasicNameValuePair("dst", destinationClientId));
            postParameters.add(new BasicNameValuePair("grant_type", grantType));
            long ts = System.currentTimeMillis()/1000;
            postParameters.add(new BasicNameValuePair("ts",String.valueOf(ts)));
            postParameters.add(new BasicNameValuePair("sign",
                    serviceContext.signCgiParamsForTvm(String.valueOf(ts),destinationClientId)));
            postRequest.setEntity(new UrlEncodedFormEntity(postParameters));

            try(CloseableHttpResponse response = client.execute(postRequest)){
                String jsonString = "";
                try(InputStream is = response.getEntity().getContent()) {
                    jsonString = IOUtils.toString(is,"utf-8");
                    JSONObject obj = new JSONObject(jsonString);
                    String tvmTicketBody = obj.getJSONObject(destinationClientId).getString("ticket");
                    return tvmTicketBody;
                } catch (JSONException e) {
                    log.error("Unexpected json input {}", jsonString);
                }
            }
        } catch (UnsupportedEncodingException e) {
            log.error("Unsupported encoding", e);
        } catch (IOException e) {
            log.error("IOE", e);
        } catch (NoSuchAlgorithmException e) {
            log.error("No such algorithm", e);
        } catch (KeyManagementException e) {
            log.error("KeyManagementException", e);
        } catch (KeyStoreException e) {
            log.error("KeyStoreException",e);
        }
        return "";
    }

}
