package xyz.gianlu.librespot.handler;

import com.spotify.Mercury;
import com.spotify.metadata.Metadata;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import org.cache2k.Cache;
import xyz.gianlu.librespot.UrlParse;
import xyz.gianlu.librespot.mercury.JsonMercuryRequest;
import xyz.gianlu.librespot.mercury.MercuryClient;
import xyz.gianlu.librespot.mercury.MercuryRequests;
import xyz.gianlu.librespot.mercury.model.ArtistId;

import java.io.IOException;
import java.io.OutputStream;
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.ArrayList;
import java.util.Arrays;
import java.lang.StringBuilder;
import java.lang.reflect.Type;
import java.net.URL;
import java.net.URLConnection;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;  

import java.sql.*;



// This class may get merged with PlayCountHandler, as most of it is basically the same.
public class ArtistInfoHandler implements HttpHandler {
    private MercuryClient mercuryClient;
    private UrlParse urlParse;
    private Cache<String, String> cache;

    public ArtistInfoHandler(MercuryClient mc, Cache<String, String> cache) {
        this.mercuryClient = mc;
        this.urlParse = new UrlParse();
        this.cache = cache;
    }

    private class MyDto {
        Map<String, String> content;
        Map<String, String> rendered;
        String origin;
        String url;
    }
    
    
    @Override
    public void handle(HttpExchange httpEx) throws IOException {
        String response;
        String albumList;
        System.setProperty("http.agent", "*/*");

        int statusCode;
        

        if (httpEx.getRequestMethod().equals("GET")) {
            Map<String, Object> res = new HashMap<>();
            if (httpEx.getRequestURI().getQuery() == null) {
                statusCode = 400;
                res.put("success", false);
                res.put("data", "artistid is not defined in the query");
                response = String.format("{\"success\": %s, \"data\": \"%s\"}", res.get("success"), res.get("data"));
            } else {
                Map<String, List<String>> query = urlParse.parse(httpEx.getRequestURI().getQuery());
                if (!query.containsKey("artistid")) {
                    statusCode = 400;
                    res.put("success", false);
                    res.put("data", "artistid is not defined in the query");
                    response = String.format("{\"success\": %s, \"data\": \"%s\"}", res.get("success"), res.get("data"));
                } else if (query.get("artistid").get(0).length() != 22) {
                    statusCode = 400;
                    res.put("success", false);
                    res.put("data", "artistid is invalid; artistid length does not equal 22");
                    response = String.format("{\"success\": %s, \"data\": \"%s\"}", res.get("success"), res.get("data"));
                } else {
                    String artistId = query.get("artistid").get(0);
                    if (cache.containsKey("artist:" + artistId)) {
                        statusCode = 200;
                        response = cache.get("artist:" + artistId);
                    } else {
                        try {
                            MercuryRequests.GenericJsonWrapper respInfo = this.mercuryClient.sendSync(MercuryRequests.getArtistInfo(artistId)); // Get artist info with artistId

                            statusCode = 200;
                            res.put("success", true);
                            res.put("dataInfo", respInfo.obj);

                            response = String.format("{\"success\": %s", res.get("success"));
                            albumList = String.format("{\"data\": %s}", res.get("dataInfo"));
                            
                            String[] split = albumList.split("\"uri\":\"spotify:album:");

                            List<String> listAlbumIDs = new ArrayList<String>();
                            String exclusions = "";
                            
                            //List<String> exclusions = this.mercuryClient.sendSync(MercuryRequests.getArtistExclusions(artistId)); // Get artist albums with no new stream data
                            int count = 0;
                            int maxTries = 3;
                            while(true) {
	                            try {
	                            	System.out.println("Try "+count);
		                            URLConnection connection = new URL("http://chartmasters.chartmasters-api.com/wp-json/wp/v2/pages/13179?artist_id="+ artistId).openConnection();
		                            connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.95 Safari/537.11");
		                            connection.connect();
		                            BufferedReader r  = new BufferedReader(new InputStreamReader(connection.getInputStream(), Charset.forName("UTF-8")));
		                            
		                            exclusions = r.readLine();
		                            break;
	                            }
	                            catch (Throwable e) { 
	                            	count = count +1;
	                            	if (count == maxTries) {
	                            		e.printStackTrace(); 
	                            	}
	                            } 
                            }
	                        if(exclusions != ""){
	                            String[] exclusionSplit1 = exclusions.split("\\[");
	                            String[] exclusionSplit2 = exclusionSplit1[1].split("\\]");
	                            String stringOfExclusion = exclusionSplit2[0].replace("\"","");
	                            stringOfExclusion = stringOfExclusion.replace("\\","");
	                            String[] stringOfExclusions = stringOfExclusion.split(",");
	                            for (int i = 0; i < stringOfExclusions.length; i++) {
	                            	listAlbumIDs.add(stringOfExclusions[i]);
	                            }
	                        }

                            for (int i = 2; i <= split.length-1; i++) { // starts at 17 with dataInfo displayed
                            	//System.out.println("i: "+i);
                            	String albumId = split[i].substring(0, 22);
                            	
                            	if (listAlbumIDs.contains(albumId)) {
                            	    continue;
                            	}
                            	
                            	listAlbumIDs.add(albumId);

                            	//System.out.println("albumId: "+albumId);
                                try { 
                                	MercuryRequests.GenericJsonWrapper resp = this.mercuryClient.sendSync(MercuryRequests.getAlbumInfo(albumId));
                                	//System.out.println("ok");

                                	res.put("success", true);
                                    res.put("data", resp.obj);

                                    //response = response + String.format("{\"success\": %s, \"data\": %s}", res.get("success"), res.get("data"));
                                    response = response + String.format(",\"%s\":%s", albumId, res.get("data"));
                                } 
                                catch (Throwable e) { 
                                    e.printStackTrace(); 
                                } 
                                
                            }
                            response = response + String.format("}");

                        } catch (Exception e) {
                            res.put("success", false);
                            if (e.getMessage().startsWith("status: ")) {
                                statusCode = Integer.parseInt(e.getMessage().substring(8));
                                if (statusCode == 404) {
                                    res.put("data", "artistid invalid; couldn't find artist");
                                } else {
                                    e.printStackTrace();
                                    res.put("data", "An unknown error has occurred; logged to console");
                                }
                            } else {
                                statusCode = 500;
                                e.printStackTrace();
                                res.put("data", "An unknown error has occurred; logged to console");
                            }

                            response = String.format("{\"success\": %s, \"data\": \"%s\"}", res.get("success"), res.get("data"));
                        }

                        if (statusCode == 200) { // If response was successful, save response in cache
                            cache.putIfAbsent("artist:" + artistId, response);
                        }
                    }
                }

            }
        } else { // Invalid request type
            statusCode = 404;
            response = "Cannot " + httpEx.getRequestMethod() + " " + httpEx.getRequestURI().toString();
        }

        httpEx.getResponseHeaders().set("Content-Type", "application/json; charset=utf-8");
        httpEx.sendResponseHeaders(statusCode, response.getBytes().length);
        OutputStream os = httpEx.getResponseBody();
        os.write(response.getBytes());
        os.close();
    }
}
