package com.bol.lazybot.hipchat.client;

import com.bol.lazybot.hipchat.installations.Installation;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Throwables;
import com.google.inject.assistedinject.Assisted;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;

import javax.inject.Inject;
import java.io.IOException;

import static com.bol.lazybot.utils.JacksonUtils.serialize;

@Slf4j
public class RoomApiHttp implements RoomApi {
    private final ObjectMapper objectMapper;
    private final OkHttpClient httpClient;
    private final OAuthApi oAuthApi;
    private final Installation installation;
    private String token;

    @Inject
    public RoomApiHttp(
            final ObjectMapper objectMapper,
            final OkHttpClient httpClient,
            final OAuthApi oAuthApi,
            @Assisted final Installation installation) {
        this.objectMapper = objectMapper;
        this.httpClient = httpClient;
        this.oAuthApi = oAuthApi;
        this.installation = installation;
        this.token = refreshOAuthToken();
    }

    @Override
    public void sendNotification(final Notification notification) {
        performRequest(new Request.Builder()
                .url("https://api.hipchat.com/v2/room/" + installation.getRoomId() + "/notification")
                .post(RequestBody.create(MediaType.parse("application/json"), serialize(objectMapper, notification))));
    }

    @Override
    public void createWebhook(final CreateWebhookRequest createWebhookRequest) {
        performRequest(new Request.Builder()
                .url("https://api.hipchat.com/v2/room/" + installation.getRoomId() + "/extension/webhook/" + createWebhookRequest.getKey())
                .put(RequestBody.create(MediaType.parse("application/json"), serialize(objectMapper, createWebhookRequest))));
    }

    private void performRequest(Request.Builder request) {
        request
                .header("Content-Type", "application/json")
                .header("Authorization", "Bearer " + token);

        int retryCount = 5;
        while (retryCount-- != 0) {
            try {
                final Response response = httpClient.newCall(request.build()).execute();
                if (response.code() == 401) token = refreshOAuthToken();
                return;
            } catch (IOException e) {
                log.error("Could not perform call", e);
            }
        }
    }

    private String refreshOAuthToken() {
        try {
            return oAuthApi.requestToken(installation.getOauthId(), installation.getOauthSecret()).getAccessToken();
        } catch (Exception e) {
            log.error("Could not get OAuth token!", e);
            throw Throwables.propagate(e);
        }
    }
}

@@ -1036,50 +1036,8 @@
 on;%0A
-        this.token = refreshOAuthToken();%0A
     
@@ -1883,33 +1883,16 @@
  request
-%0A                
 .header(
@@ -1930,68 +1930,8 @@
 on%22)
-%0A                .header(%22Authorization%22, %22Bearer %22 + token)
 ;%0A%0A 
@@ -2003,32 +2003,165 @@
           try %7B%0A
+                if (token == null) token = refreshOAuthToken();%0A%0A                request.header(%22Authorization%22, %22Bearer %22 + token);%0A
                 
@@ -2273,67 +2273,155 @@
 e() 
-== 401) token = refreshOAuthToken();%0A                return
+%3C 400) return;%0A%0A                // 401 means the OAuth may be invalid, so let's refresh it%0A                if (response.code() == 401) token = null
 ;%0A  

Refresh it correctly this time :)