/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package DataLayer;

import FunctionLayer.CustomError;
import FunctionLayer.StringObject;
import com.google.common.base.Stopwatch;
import com.google.common.collect.MapMaker;
import java.beans.PropertyVetoException;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author install1
 */
public class DataMapper {

    public static final long EXPIRE_TIME_IN_SECONDS = TimeUnit.SECONDS.convert(15, TimeUnit.MINUTES);
    public static DataMapper instance = new DataMapper();
    private volatile boolean called;
    private final ConcurrentMap<Integer, StringObject> soEventContentCache;

    public DataMapper() {
        this.soEventContentCache = new MapMaker().concurrencyLevel(2).makeMap();
    }

    public List<StringObject> getAllMapValues() {
        List<StringObject> MapColoumns = new ArrayList(soEventContentCache.values());
        return MapColoumns;
    }

    public void insertIntoDBEventContent(ConcurrentMap<Integer, String> EventContentMap) {
        String SQL_Delete = "delete from Maps";
        String l_sSQL = "INSERT INTO `EventContent` (`title`,`Rewards`,`Leaders`,`datum`,`hours`) VALUES (?, ?, ?, ?, ?)";
        String l_SQLMaps = "INSERT INTO `Maps` (`MapNames`) VALUES (?)";
        List<String> maps = new ArrayList();
        try (Connection l_cCon = DBCPDataSource.getConnection()) {
            try (PreparedStatement s = l_cCon.prepareStatement(SQL_Delete)) {
                s.executeUpdate();
            }
            SQL_Delete = "delete from EventContent";
            try (PreparedStatement s = l_cCon.prepareStatement(SQL_Delete)) {
                s.executeUpdate();
            }
            try (PreparedStatement s = l_cCon.prepareStatement(l_sSQL)) {
                int i = 1;
                for (String str : EventContentMap.values()) {
                    if (i < 6) {
                        //System.out.println("str: " + str + "\n");
                        s.setString(i, str);
                        i++;
                    } else {
                        maps.add(str);
                    }
                }
                s.executeUpdate();
            }
            try (PreparedStatement s = l_cCon.prepareStatement(l_SQLMaps)) {
                for (String strMap : maps) {
                    if (!maps.isEmpty()) {
                        s.setString(1, strMap);
                        s.addBatch();
                    }
                }
                s.executeBatch();
            }
        } catch (SQLException ex) {
            Logger.getLogger(DataMapper.class.getName()).log(Level.SEVERE, null, ex);
        }
        called = false;
    }

    private Map<Integer, StringObject> getCache() throws SQLException, IOException, CustomError {
        List<StringObject> stro;
        stro = GetEventContentFromDBTable();
        LinkedHashMap<Integer, StringObject> LHM = new LinkedHashMap();
        for (int i = 0; i < stro.size(); i++) {
            LHM.put(i, stro.get(i));
        }
        return LHM;
    }

    public synchronized void initialization() throws SQLException, IOException, CustomError {
        if (called == false) {
            soEventContentCache.putAll(getCache());
            for (int i = 0; i < soEventContentCache.size(); i++) {
                soEventContentCache.get(i).setEventContent(modifyEventContent(soEventContentCache.get(i).getEventContent(), i));
            }
            called = true;
        }
    }

    public static String modifyEventContent(String str, int i) {
        StringBuilder sb = new StringBuilder();
        switch (i) {
            case 0: {
                sb.append(str);
                break;
            }
            case 1: {
                str = str.trim();
                sb.append(str);
                sb.insert(0, "Rewards: ");
                break;
            }
            case 2: {
                sb.append(str);
                sb.insert(0, "Leaders: ");
                break;
            }
            case 3: {
                sb.append(str);
                sb.insert(0, "Date: ");
                break;
            }
            case 4: {
                sb.append(str);
                sb.insert(0, "Hour: ");
                sb.append("GMT +1");
                break;
            }
            default: {
                sb.append(str);
                sb.insert(0, "Map: ");
                break;
            }
        }
        return sb.toString();
    }

    public static List<StringObject> GetEventContentFromDBTable() throws CustomError {
        /*
        0 = title
        1 = rewards
        2 = leaders
        3 = datum
        4 = hours
        5 = maps
         */
        List<StringObject> str = new ArrayList();
        Connection l_cCon = null;
        PreparedStatement l_pStatement = null;
        ResultSet l_rsSearch = null;
        try {
            l_cCon = DBCPDataSource.getConnection();
            String l_sSQL = "SELECT * FROM `EventContent`";
            l_pStatement = l_cCon.prepareStatement(l_sSQL);
            l_rsSearch = l_pStatement.executeQuery();
            l_rsSearch.next();
            for (int i = 1; i < 6; i++) {
                StringObject so = new StringObject(l_rsSearch.getString(i));
                str.add(so);
            }
            l_sSQL = "SELECT * FROM `Maps`";
            l_pStatement = l_cCon.prepareStatement(l_sSQL);
            l_rsSearch = l_pStatement.executeQuery();
            while (l_rsSearch.next()) {
                StringObject so = new StringObject(l_rsSearch.getString(1));
                str.add(so);
            }
        } catch (SQLException ex) {
            throw new CustomError("failed in DataMapper  " + ex.getMessage());
        } finally {
            CloseConnections(l_pStatement, l_rsSearch, l_cCon);
        }
        return str;
    }

    public static void CloseConnections(PreparedStatement ps, ResultSet rs, Connection con) {
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException ex) {
                Logger.getLogger(DataMapper.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        if (ps != null) {
            try {
                ps.close();
            } catch (SQLException ex) {
                Logger.getLogger(DataMapper.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        if (con != null) {
            try {
                con.close();
            } catch (SQLException ex) {
                Logger.getLogger(DataMapper.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }
}
