/*
 * Copyright 2013-2014 eBay Software Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.kylinolap.cube;

import com.kylinolap.common.KylinConfig;
import com.kylinolap.common.persistence.JsonSerializer;
import com.kylinolap.common.persistence.ResourceStore;
import com.kylinolap.common.persistence.Serializer;
import com.kylinolap.common.restclient.Broadcaster;
import com.kylinolap.common.restclient.SingleValueCache;
import com.kylinolap.cube.exception.CubeIntegrityException;
import com.kylinolap.cube.project.ProjectInstance;
import com.kylinolap.cube.project.ProjectManager;
import com.kylinolap.dict.Dictionary;
import com.kylinolap.dict.DictionaryInfo;
import com.kylinolap.dict.DictionaryManager;
import com.kylinolap.dict.lookup.HiveTable;
import com.kylinolap.dict.lookup.LookupStringTable;
import com.kylinolap.dict.lookup.SnapshotManager;
import com.kylinolap.dict.lookup.SnapshotTable;
import com.kylinolap.metadata.MetadataManager;
import com.kylinolap.metadata.model.cube.CubeDesc;
import com.kylinolap.metadata.model.cube.DimensionDesc;
import com.kylinolap.metadata.model.cube.TblColRef;
import com.kylinolap.metadata.model.schema.ColumnDesc;
import com.kylinolap.metadata.model.schema.TableDesc;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author yangli9
 */
public class CubeManager {

    private static String ALPHA_NUM = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    private static int HBASE_TABLE_LENGTH = 10;

    private static final Serializer<CubeInstance> CUBE_SERIALIZER = new JsonSerializer<CubeInstance>(
            CubeInstance.class);

    private static final Logger logger = LoggerFactory.getLogger(CubeManager.class);

    // static cached instances
    private static final ConcurrentHashMap<KylinConfig, CubeManager> CACHE =
            new ConcurrentHashMap<KylinConfig, CubeManager>();

    public static CubeManager getInstance(KylinConfig config) {
        CubeManager r = CACHE.get(config);
        if (r != null) {
            return r;
        }

        synchronized (CubeManager.class) {
            r = CACHE.get(config);
            if (r != null) {
                return r;
            }
            try {
                r = new CubeManager(config);
                CACHE.put(config, r);
                return r;
            } catch (IOException e) {
                throw new IllegalStateException("Failed to init CubeManager from " + config, e);
            }
        }
    }

    public static void clearCache() {
        CACHE.clear();
    }

    public static synchronized void removeInstance(KylinConfig config) {
        CACHE.remove(config);
    }

    // ============================================================================

    private KylinConfig config;
    // cube name ==> CubeInstance
    private SingleValueCache<String, CubeInstance> cubeMap = new SingleValueCache<String, CubeInstance>(
            Broadcaster.TYPE.CUBE);
    // "table/column" ==> lookup table
    private SingleValueCache<String, LookupStringTable> lookupTables =
            new SingleValueCache<String, LookupStringTable>(Broadcaster.TYPE.METADATA);

    // for generation hbase table name of a new segment
    private HashSet<String> usedStorageLocation = new HashSet<String>();

    private CubeManager(KylinConfig config) throws IOException {
        logger.info("Initializing CubeManager with config " + config);
        this.config = config;

        loadAllCubeInstance();
    }

    public List<CubeInstance> listAllCubes() {
        return new ArrayList<CubeInstance>(cubeMap.values());
    }

    public CubeInstance getCube(String cubeName) {
        cubeName = cubeName.toUpperCase();
        return cubeMap.get(cubeName);
    }

    /**
     * Get related Cubes by cubedesc name.
     * By default, the desc name will be translated into upper case.
     *
     * @param descName CubeDesc name
     * @return
     */
    public List<CubeInstance> getCubesByDesc(String descName) {

        descName = descName.toUpperCase();
        List<CubeInstance> list = listAllCubes();
        List<CubeInstance> result = new ArrayList<CubeInstance>();
        Iterator<CubeInstance> it = list.iterator();
        while (it.hasNext()) {
            CubeInstance ci = it.next();
            if (descName.equals(ci.getDescName())) {
                result.add(ci);
            }
        }
        return result;
    }

    public void buildInvertedIndexDictionary(CubeSegment cubeSeg, String factColumnsPath) throws IOException {
        MetadataManager metaMgr = getMetadataManager();
        DictionaryManager dictMgr = getDictionaryManager();

        TableDesc tableDesc = metaMgr.getTableDesc(cubeSeg.getCubeDesc().getFactTable());
        for (ColumnDesc colDesc : tableDesc.getColumns()) {
            TblColRef col = new TblColRef(colDesc);
            DictionaryInfo dict = dictMgr.buildDictionary(null, col, factColumnsPath);
            cubeSeg.putDictResPath(col, dict.getResourcePath());
        }

        saveResource(cubeSeg.getCubeInstance());
    }

    public DictionaryInfo buildDictionary(CubeSegment cubeSeg, TblColRef col, String factColumnsPath)
            throws IOException {
        if (!cubeSeg.getCubeDesc().getRowkey().isUseDictionary(col))
            return null;

        DictionaryManager dictMgr = getDictionaryManager();
        DictionaryInfo dictInfo = dictMgr.buildDictionary(cubeSeg.getCubeDesc(), col, factColumnsPath);
        cubeSeg.putDictResPath(col, dictInfo.getResourcePath());

        saveResource(cubeSeg.getCubeInstance());

        return dictInfo;
    }

    /**
     * return null if no dictionary for given column
     */
    public Dictionary<?> getDictionary(CubeSegment cubeSeg, TblColRef col) {
        DictionaryInfo info = null;
        try {
            DictionaryManager dictMgr = getDictionaryManager();
            //logger.info("Using metadata url " + metadataUrl + " for DictionaryManager");
            String dictResPath = cubeSeg.getDictResPath(col);
            if (dictResPath == null)
                return null;

            info = dictMgr.getDictionaryInfo(dictResPath);
            if (info == null)
                throw new IllegalStateException("No dictionary found by " + dictResPath
                        + ", invalid cube state; cube segment" + cubeSeg.getName() + ", col " + col);
        } catch (IOException e) {
            throw new IllegalStateException("Failed to get dictionary for cube segment" + cubeSeg.getName()
                    + ", col" + col, e);
        }

        return info == null ? null : info.getDictionaryObject();
    }

    public SnapshotTable buildSnapshotTable(CubeSegment cubeSeg, String lookupTable, boolean reuseExisting)
            throws IOException {
        MetadataManager metaMgr = getMetadataManager();
        SnapshotManager snapshotMgr = getSnapshotManager();

        HiveTable hiveTable = new HiveTable(metaMgr, lookupTable);
        TableDesc tableDesc = metaMgr.getTableDesc(lookupTable);
        SnapshotTable snapshot = snapshotMgr.buildSnapshot(hiveTable, tableDesc, reuseExisting);

        cubeSeg.putSnapshotResPath(lookupTable, snapshot.getResourcePath());

        saveResource(cubeSeg.getCubeInstance());

        return snapshot;
    }

    // sync on update
    public CubeInstance dropCube(String cubeName) throws IOException {
        logger.info("Dropping cube '" + cubeName + "'");
        // load projects before remove cube from project
        List<ProjectInstance> projects = ProjectManager.getInstance(config).getProjects(cubeName);

        ResourceStore store = getStore();

        //delete cube instance and cube desc
        CubeInstance cube = getCube(cubeName);
        store.deleteResource(cube.getDescriptor().getResourcePath());
        store.deleteResource(cube.getResourcePath());

        //delete cube from project
        ProjectManager.getInstance(config).removeCubeFromProjects(cubeName);

        // clean cube cache
        this.afterCubeDroped(cube, projects);

        return cube;
    }

    // sync on update
    public CubeInstance createCube(String cubeName, String projectName, CubeDesc desc, String owner)
            throws IOException {
        logger.info("Creating cube '" + projectName + "-->" + cubeName + "' from desc '" + desc.getName()
                + "'");

        // save cube resource
        CubeInstance cube = CubeInstance.create(cubeName, projectName, desc);
        cube.setOwner(owner);
        saveResource(cube);

        ProjectManager.getInstance(config).updateCubeToProject(cubeName, projectName, owner);

        return cube;
    }

    public CubeInstance updateCube(CubeInstance cube) throws IOException {
        logger.info("Updating cube instance '" + cube.getName());

        // save resource
        saveResource(cube);

        logger.info("Cube with " + cube.getSegments().size() + " segments is saved");

        return cube;
    }

    public List<CubeSegment> allocateSegments(CubeInstance cubeInstance, CubeBuildTypeEnum buildType,
                                              long startDate, long endDate) throws IOException, CubeIntegrityException {
        if (cubeInstance.getBuildingSegments().size() > 0) {
            throw new RuntimeException("There is already a allocating segment!");
        }
        List<CubeSegment> segments = new ArrayList<CubeSegment>();

        if (null != cubeInstance.getDescriptor().getCubePartitionDesc().getPartitionDateColumn()) {
            if (startDate == 0 && cubeInstance.getSegments().size() == 0) {
                startDate = cubeInstance.getDescriptor().getCubePartitionDesc().getPartitionDateStart();
            }

            // incremental build
            CubeSegment lastSegment = null;
            for (CubeSegment segment : cubeInstance.getSegments()) {
                if (segment.getDateRangeStart() == startDate) {
                    // refresh or merge
                    segments.add(buildSegment(cubeInstance, startDate, endDate));
                }
                if (segment.getDateRangeStart() < startDate && startDate < segment.getDateRangeEnd()) {
                    // delete-insert
                    segments.add(buildSegment(cubeInstance, segment.getDateRangeStart(), startDate));
                    segments.add(buildSegment(cubeInstance, startDate, endDate));
                }
                lastSegment = segment;
            }

            // append
            if (null == lastSegment || (lastSegment.getDateRangeEnd() == startDate)) {
                segments.add(buildSegment(cubeInstance, startDate, endDate));
            }
        } else {
            segments.add(buildSegment(cubeInstance, 0, 0));
        }

        validateNewSegments(cubeInstance, buildType, segments);

        if (buildType == CubeBuildTypeEnum.MERGE) {
            this.makeDictForNewSegment(cubeInstance, segments.get(0));
            this.makeSnapshotForNewSegment(cubeInstance, segments.get(0));
        }

        cubeInstance.getSegments().addAll(segments);
        Collections.sort(cubeInstance.getSegments());

        this.updateCube(cubeInstance);

        return segments;
    }

    public String getHBaseStorageLocationPrefix() {
        return getHbaseStorageLocationPrefix(config.getMetadataUrl());
    }

    public static String getHbaseStorageLocationPrefix(String hbaseMetadataUrl) {
        String defaultPrefix = "KYLIN_CUBE_";

        if (StringUtils.containsIgnoreCase(hbaseMetadataUrl, "hbase:")) {
            int cut = hbaseMetadataUrl.indexOf('@');
            String tmp = cut < 0 ? defaultPrefix : hbaseMetadataUrl.substring(0, cut);
            String prefix = StringUtils.replace(tmp, "_metadata", "");
            return (prefix + "_CUBE_").toUpperCase();
        } else {
            return defaultPrefix;
        }
    }

    public void updateSegmentOnJobSucceed(CubeInstance cubeInstance, CubeBuildTypeEnum buildType,
                                          String segmentName, String lastBuildJobUuid, long lastBuildTime, long sizeKB,
                                          long sourceRecordCount, long sourceRecordsSize) throws IOException, CubeIntegrityException {

        List<CubeSegment> segmentsInNewStatus = cubeInstance.getSegments(CubeSegmentStatusEnum.NEW);
        CubeSegment cubeSegment = cubeInstance.getSegment(segmentName, CubeSegmentStatusEnum.NEW);

        switch (buildType) {
            case BUILD:
                if (segmentsInNewStatus.size() == 1) {// if this the last segment in status of NEW
                    // remove all the rebuilding/impacted segments
                    cubeInstance.getSegments().removeAll(cubeInstance.getRebuildingSegments());
                }
                break;
            case MERGE:
                cubeInstance.getSegments().removeAll(cubeInstance.getMergingSegments());
                break;
        }

        cubeSegment.setLastBuildJobID(lastBuildJobUuid);
        cubeSegment.setLastBuildTime(lastBuildTime);
        cubeSegment.setSizeKB(sizeKB);
        cubeSegment.setSourceRecords(sourceRecordCount);
        cubeSegment.setSourceRecordsSize(sourceRecordsSize);
        if (segmentsInNewStatus.size() == 1) {
            cubeSegment.setStatus(CubeSegmentStatusEnum.READY);
            cubeInstance.setStatus(CubeStatusEnum.READY);

            for (CubeSegment seg : cubeInstance.getSegments(CubeSegmentStatusEnum.READY_PENDING)) {
                seg.setStatus(CubeSegmentStatusEnum.READY);
            }
        } else {
            cubeSegment.setStatus(CubeSegmentStatusEnum.READY_PENDING);
        }
        this.updateCube(cubeInstance);
    }

    public void updateSegmentOnJobDiscard(CubeInstance cubeInstance, String segmentName) throws IOException,
            CubeIntegrityException {
        for (int i = 0; i < cubeInstance.getSegments().size(); i++) {
            CubeSegment segment = cubeInstance.getSegments().get(i);
            if (segment.getName().equals(segmentName) && segment.getStatus() != CubeSegmentStatusEnum.READY) {
                cubeInstance.getSegments().remove(segment);
            }
        }
        updateCube(cubeInstance);
    }

    /**
     * After cube update, reload cube related cache
     *
     * @param cube
     */
    public void loadCubeCache(CubeInstance cube) {
        try {
            loadCubeInstance(cube.getResourcePath());
        } catch (IOException e) {
            logger.error(e.getLocalizedMessage(), e);
        }
    }

    /**
     * After cube deletion, remove cube related cache
     *
     * @param cube
     */
    public void removeCubeCache(CubeInstance cube) {
        cubeMap.remove(cube.getName().toUpperCase());

        for (CubeSegment segment : cube.getSegments()) {
            usedStorageLocation.remove(segment.getName());
        }
    }

    public LookupStringTable getLookupTable(CubeSegment cubeSegment, DimensionDesc dim) {

        String tableName = dim.getTable();
        String[] pkCols = dim.getJoin().getPrimaryKey();
        String key = tableName + "#" + StringUtils.join(pkCols, ",");

        LookupStringTable r = lookupTables.get(key);
        if (r == null) {
            String snapshotResPath = cubeSegment.getSnapshotResPath(tableName);
            if (snapshotResPath == null)
                throw new IllegalStateException("No snaphot for table '" + tableName
                        + "' found on cube segment" + cubeSegment.getCubeInstance().getName() + "/"
                        + cubeSegment.getName());

            try {
                SnapshotTable snapshot = getSnapshotManager().getSnapshotTable(snapshotResPath);
                TableDesc tableDesc = getMetadataManager().getTableDesc(tableName);
                r = new LookupStringTable(tableDesc, pkCols, snapshot);
            } catch (IOException e) {
                throw new IllegalStateException("Failed to load lookup table " + tableName
                        + " from snapshot " + snapshotResPath, e);
            }

            lookupTables.putLocal(key, r);
        }

        return r;
    }

    /**
     * For the new segment, we need to create dictionaries for it, too.
     * For those dictionaries on fact table, create it by merging underlying dictionaries
     * For those dictionaries on lookup table, just copy it from any one of the merging segments,
     * it's ganranteed to be consistent(checked in CubeSegmentValidator)
     *
     * @param cube
     * @param newSeg
     * @throws IOException
     */
    private void makeDictForNewSegment(CubeInstance cube, CubeSegment newSeg) throws IOException {
        List<CubeSegment> mergingSegments = cube.getMergingSegments(newSeg);

        HashSet<TblColRef> colsNeedMeringDict = new HashSet<TblColRef>();
        HashSet<TblColRef> colsNeedCopyDict = new HashSet<TblColRef>();
        DictionaryManager dictMgr = this.getDictionaryManager();

        for (DimensionDesc dim : cube.getDescriptor().getDimensions()) {
            for (TblColRef col : dim.getColumnRefs()) {
                if (newSeg.getCubeDesc().getRowkey().isUseDictionary(col)) {
                    if (cube.getDescriptor()
                            .getFactTable()
                            .equalsIgnoreCase(
                                    (String) dictMgr.decideSourceData(cube.getDescriptor(), col, null)[0])) {
                        colsNeedMeringDict.add(col);
                    } else {
                        colsNeedCopyDict.add(col);
                    }
                }
            }
        }

        for (TblColRef col : colsNeedMeringDict) {
            logger.info("Merging fact table dictionary on : " + col);
            List<DictionaryInfo> dictInfos = new ArrayList<DictionaryInfo>();
            for (CubeSegment segment : mergingSegments) {
                logger.info("Including fact table dictionary of segment : " + segment.getName());
                DictionaryInfo dictInfo = dictMgr.getDictionaryInfo(segment.getDictResPath(col));
                dictInfos.add(dictInfo);
            }
            this.mergeDictionaries(newSeg, dictInfos, col);
        }

        for (TblColRef col : colsNeedCopyDict) {
            String path = mergingSegments.get(0).getDictResPath(col);
            newSeg.putDictResPath(col, path);
        }
    }

    /**
     * make snapshots for the new segment by copying from one of the
     * underlying merging segments.
     * it's ganranteed to be consistent(checked in CubeSegmentValidator)
     *
     * @param cube
     * @param newSeg
     */
    private void makeSnapshotForNewSegment(CubeInstance cube, CubeSegment newSeg) {
        List<CubeSegment> mergingSegments = cube.getMergingSegments(newSeg);
        for (Map.Entry<String, String> entry : mergingSegments.get(0).getSnapshots().entrySet()) {
            newSeg.putSnapshotResPath(entry.getKey(), entry.getValue());
        }
    }

    private DictionaryInfo mergeDictionaries(CubeSegment cubeSeg, List<DictionaryInfo> dicts, TblColRef col)
            throws IOException {
        DictionaryManager dictMgr = getDictionaryManager();
        DictionaryInfo dictInfo = dictMgr.mergeDictionary(dicts);
        cubeSeg.putDictResPath(col, dictInfo.getResourcePath());

        return dictInfo;
    }

    private void saveResource(CubeInstance cube) throws IOException {
        ResourceStore store = getStore();
        store.putResource(cube.getResourcePath(), cube, CUBE_SERIALIZER);
        this.afterCubeUpdated(cube);
    }

    private void afterCubeUpdated(CubeInstance updatedCube) {
        MetadataManager.getInstance(config).reload();
        cubeMap.put(updatedCube.getName().toUpperCase(), updatedCube);

        for (ProjectInstance project : ProjectManager.getInstance(config).getProjects(updatedCube.getName())) {
            try {
                ProjectManager.getInstance(config).loadProjectCache(project, true);
            } catch (IOException e) {
                logger.error(e.getLocalizedMessage(), e);
            }
        }
    }

    private void afterCubeDroped(CubeInstance droppedCube, List<ProjectInstance> projects) {
        MetadataManager.getInstance(config).reload();
        removeCubeCache(droppedCube);

        if (null != projects) {
            for (ProjectInstance project : projects) {
                try {
                    ProjectManager.getInstance(config).loadProjectCache(project, true);
                } catch (IOException e) {
                    logger.error(e.getLocalizedMessage(), e);
                }
            }
        }
    }

    /**
     * @param cubeInstance
     * @param startDate    (pass 0 if full build)
     * @param endDate      (pass 0 if full build)
     * @return
     */
    private CubeSegment buildSegment(CubeInstance cubeInstance, long startDate, long endDate) {
        CubeSegment incrementalSeg = new CubeSegment();
        String incrementalSegName = CubeSegment.getSegmentName(startDate, endDate);
        incrementalSeg.setName(incrementalSegName);
        incrementalSeg.setDateRangeStart(startDate);
        incrementalSeg.setDateRangeEnd(endDate);
        incrementalSeg.setStatus(CubeSegmentStatusEnum.NEW);
        incrementalSeg.setStorageLocationIdentifier(generateStorageLocation());

        incrementalSeg.setCubeInstance(cubeInstance);

        return incrementalSeg;
    }

    private String generateStorageLocation() {
        String namePrefix = getHBaseStorageLocationPrefix();
        String tableName = "";
        do {
            StringBuffer sb = new StringBuffer();
            sb.append(namePrefix);
            for (int i = 0; i < HBASE_TABLE_LENGTH; i++) {
                int idx = (int) (Math.random() * ALPHA_NUM.length());
                sb.append(ALPHA_NUM.charAt(idx));
            }
            tableName = sb.toString();
        } while (this.usedStorageLocation.contains(tableName));

        return tableName;
    }

    /**
     */
    private void validateNewSegments(CubeInstance cubeInstance, CubeBuildTypeEnum buildType,
                                     List<CubeSegment> newSegments) throws CubeIntegrityException {
        if (null == cubeInstance.getDescriptor().getCubePartitionDesc().getPartitionDateColumn()) {
            // do nothing for non-incremental build
            return;
        }

        if (newSegments.size() == 0) {
            throw new CubeIntegrityException("Failed to allocate any segment.");
        }

        for (CubeSegment segment : newSegments) {
            if (segment.getDateRangeEnd() <= segment.getDateRangeStart()) {
                throw new CubeIntegrityException(" end date.");
            }
        }

        CubeSegmentValidator cubeSegmentValidator =
                CubeSegmentValidator.getCubeSegmentValidator(buildType, cubeInstance.getDescriptor()
                        .getCubePartitionDesc().getCubePartitionType());
        cubeSegmentValidator.validate(cubeInstance, newSegments);
    }

    private void loadAllCubeInstance() throws IOException {
        ResourceStore store = getStore();
        List<String> paths = store.collectResourceRecursively(ResourceStore.CUBE_RESOURCE_ROOT, ".json");

        logger.debug("Loading Cube from folder "
                + store.getReadableResourcePath(ResourceStore.CUBE_RESOURCE_ROOT));

        for (String path : paths) {
            loadCubeInstance(path);
        }

        logger.debug("Loaded " + paths.size() + " Cube(s)");
    }

    private synchronized CubeInstance loadCubeInstance(String path) throws IOException {
        ResourceStore store = getStore();
        logger.debug("Loading CubeInstance " + store.getReadableResourcePath(path));

        CubeInstance cubeInstance = null;
        try {
            cubeInstance = store.getResource(path, CubeInstance.class, CUBE_SERIALIZER);
            cubeInstance.setConfig(config);

            if (StringUtils.isBlank(cubeInstance.getName()))
                throw new IllegalStateException("CubeInstance name must not be blank");

            cubeMap.putLocal(cubeInstance.getName().toUpperCase(), cubeInstance);

            for (CubeSegment segment : cubeInstance.getSegments()) {
                usedStorageLocation.add(segment.getName());
            }

            return cubeInstance;
        } catch (Exception e) {
            logger.error("Error during load cube instance " + path, e);
            return null;
        }
    }

    private MetadataManager getMetadataManager() {
        return MetadataManager.getInstance(config);
    }

    private DictionaryManager getDictionaryManager() {
        return DictionaryManager.getInstance(config);
    }

    private SnapshotManager getSnapshotManager() {
        return SnapshotManager.getInstance(config);
    }

    private ResourceStore getStore() {
        return ResourceStore.getStore(this.config);
    }
}
