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);

                            //MercuryRequests.GenericJsonWrapper respAbout = this.mercuryClient.sendSync(MercuryRequests.getArtistAbout(artistId)); // Get artist info with artistId
                            //res.put("dataAbout", respAbout.obj);
                            
                            //MercuryRequests.GenericJsonWrapper respInsights = this.mercuryClient.sendSync(MercuryRequests.getArtistInsights(artistId)); // Get artist info with artistId
                            //res.put("dataInsights", respInsights.obj);
                            
                            //response = String.format("{\"success\": %s, \"dataInfo\": %s, \"dataAbout\": %s, \"dataInsights\": %s", res.get("success"), res.get("dataInfo"), res.get("dataAbout"), res.get("dataInsights"));

                            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>();
                            
                            //List<String> exclusions = this.mercuryClient.sendSync(MercuryRequests.getArtistExclusions(artistId)); // Get artist albums with no new stream data
                            
                            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")));
                            //InputStreamReader reader  = new InputStreamReader(connection.getInputStream(), Charset.forName("UTF-8"));
                            
                            String exclusions = r.readLine();
                            /*
                            List<String> exclusions = new ArrayList<String>();
                            String line;
                            while ((line = r.readLine()) != null) {
                            	System.out.println("Nouvelle ligne : "+line);
                            	exclusions.add(line);
                            }
                            */
                            
                            //Gson gson = new Gson();
                            //List<String> listExclusion = gson.fromJson(line, new TypeToken<List<String>>() {}.getType());
                            //listExclusion.forEach(x -> System.out.println(x));
                            // In this test code i just shove the JSON here as string.
                            //List<String> exclusions = gson.fromJson("{ \"exclusions\": [\"00it4Y3J475KegT67qQ4o6\",\"03Rt2ycrWRIxHXb1j9fxOr\"] }", listType);


                            //JsonMercuryRequest<>(RawMercuryRequest.get(line, artistId)), GenericJsonWrapper.class); 

                            
                            //String[] exclusionSplit1 = exclusions.split("\"rendered\":\"\n\\[\"");
                            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]);
                            }
                            //System.out.println(Arrays.toString(exclusions.toArray()))
                            
                            //URL url = new URL("http://chartmasters.chartmasters-api.com/wp-json/wp/v2/pages/13179?artist_id="+ artistId);
                            //InputStreamReader reader = new InputStreamReader(url.openStream());
                            //MyDto exclusions = new Gson().fromJson(reader, MyDto.class);

//                        	System.out.println("exclusions: "+exclusions);
                        	
                        	//System.out.println("length: "+split.length);
                            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("}");
                            /*
                            String jsonString = response;
                            JSONObject obj = new JSONObject(jsonString);
                            JSONArray albums = obj.getJSONObject("dataInfo").getJSONObject("info").getJSONObject("releases").getJSONObject("albums").getJSONArray("releases");

                            for (int i = 0; i < albums.length(); i++)
                            {
                                String URIs = URIs+"," + albums.getJSONObject(i).getString("uri");
                            }
                            response = response.concat(URIs);  
*/
                        } 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();
    }
}
