/*
 * Copyright (C) 2007-2014, GoodData(R) Corporation. All rights reserved.
 */
package com.gooddata;

import com.gooddata.account.AccountService;
import com.gooddata.dataset.DatasetService;
import com.gooddata.gdc.DataStoreService;
import com.gooddata.gdc.GdcService;
import com.gooddata.http.client.GoodDataHttpClient;
import com.gooddata.http.client.LoginSSTRetrievalStrategy;
import com.gooddata.http.client.SSTRetrievalStrategy;
import com.gooddata.md.MetadataService;
import com.gooddata.model.ModelService;
import com.gooddata.project.ProjectService;
import org.apache.http.HttpHost;
import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.springframework.http.MediaType;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

import java.util.Arrays;

import static java.util.Collections.singletonMap;

/**
 */
public class GoodData {

    private static final String PROTOCOL = "https";
    private static final int PORT = 443;
    private static final String HOSTNAME = "secure.gooddata.com";

    private final RestTemplate restTemplate;
    private final HttpClientBuilder httpClientBuilder;
    private final String login;
    private final String password;

    public GoodData(String login, String password) {
        this(login, password, HOSTNAME);
    }

    public GoodData(String hostname, String login, String password) {
        this.login = login;
        this.password = password;
        final HttpHost host = new HttpHost(hostname, PORT, PROTOCOL);

        httpClientBuilder = HttpClientBuilder.create();
        final CloseableHttpClient httpClient = httpClientBuilder.build();
        final SSTRetrievalStrategy strategy = new LoginSSTRetrievalStrategy(httpClient, host, login, password);

        final HttpClient client = new GoodDataHttpClient(httpClient, strategy);

        final UriPrefixingClientHttpRequestFactory factory = new UriPrefixingClientHttpRequestFactory(
                new HttpComponentsClientHttpRequestFactory(client), hostname, PORT, PROTOCOL);
        restTemplate = new RestTemplate(factory);
        restTemplate.setInterceptors(Arrays.<ClientHttpRequestInterceptor>asList(
                new HeaderAddingRequestInterceptor(singletonMap("Accept", MediaType.APPLICATION_JSON_VALUE))));
    }

    public void logout() {
        getAccountService().logout();
    }

    public ProjectService getProjectService() {
       return new ProjectService(restTemplate, getAccountService());
    }

    public AccountService getAccountService() {
        return new AccountService(restTemplate);
    }

    public MetadataService getMetadataService() {
        return new MetadataService(restTemplate);
    }

    public ModelService getModelService() {
        return new ModelService(restTemplate);
    }

    public GdcService getGdcService() {
        return new GdcService(restTemplate);
    }

    public DataStoreService getDataStoreService() {
        return new DataStoreService(httpClientBuilder, getGdcService(), login, password);
    }

    public DatasetService getDatasetService() {
        return new DatasetService(restTemplate, getDataStoreService());
    }
}

@@ -1417,16 +1417,311 @@
 assword;
+%0A    private AccountService accountService;%0A    private ProjectService projectService;%0A    private MetadataService metadataService;%0A    private ModelService modelService;%0A    private GdcService gdcService;%0A    private DataStoreService dataStoreService;%0A    private DatasetService datasetService;
 %0A%0A    pu
@@ -2783,16 +2783,41 @@
 LUE))));
+%0A%0A        initServices();
 %0A    %7D%0A%0A
@@ -2947,20 +2947,17 @@
     
+ 
 return 
-new P
+p
 roje
@@ -2969,43 +2969,8 @@
 vice
-(restTemplate, getAccountService())
 ;%0A  
@@ -3041,13 +3041,9 @@
 urn 
-new A
+a
 ccou
@@ -3047,38 +3047,24 @@
 countService
-(restTemplate)
 ;%0A    %7D%0A%0A   
@@ -3125,21 +3125,17 @@
  return 
-new M
+m
 etadataS
@@ -3136,38 +3136,24 @@
 adataService
-(restTemplate)
 ;%0A    %7D%0A%0A   
@@ -3212,13 +3212,9 @@
 urn 
-new M
+m
 odel
@@ -3216,38 +3216,24 @@
 modelService
-(restTemplate)
 ;%0A    %7D%0A%0A   
@@ -3284,21 +3284,17 @@
  return 
-new G
+g
 dcServic
@@ -3298,22 +3298,8 @@
 vice
-(restTemplate)
 ;%0A  
@@ -3374,152 +3374,585 @@
 urn 
-new DataStoreService(httpClientBuilder, getGdcService(), login, password
+dataStoreService;%0A    %7D%0A%0A    public DatasetService getDatasetService() %7B%0A        return datasetService;%0A    %7D%0A%0A    private void initServices() %7B%0A        accountService = new AccountService(restTemplate);%0A        projectService = new ProjectService(restTemplate, getAccountService());%0A        metadataService = new MetadataService(restTemplate);%0A        modelService = new ModelService(restTemplate
 );%0A    
-%7D%0A%0A
     
-public DatasetService getDatasetService() %7B%0A        return
+gdcService = new GdcService(restTemplate);%0A        dataStoreService = new DataStoreService(httpClientBuilder, getGdcService(), login, password);%0A        datasetService =
  new

initialize services only once