// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.model.application.validation;

import com.yahoo.config.application.api.ApplicationFile;
import com.yahoo.config.application.api.ApplicationPackage;
import com.yahoo.config.model.deploy.DeployState;
import com.yahoo.path.Path;
import com.yahoo.searchdefinition.RankingConstant;
import com.yahoo.vespa.model.VespaModel;
import com.yahoo.vespa.model.application.validation.ConstantTensorJsonValidator.InvalidConstantTensor;
import com.yahoo.vespa.model.search.SearchDefinition;

import java.io.FileNotFoundException;

/**
 * RankingConstantsValidator validates all constant tensors (ranking constants) bundled with an application package
 *
 * @author Vegard Sjonfjell
 */

public class RankingConstantsValidator extends Validator {

    private static class ExceptionMessageCollector {

        String combinedMessage;
        boolean exceptionsOccurred = false;

        ExceptionMessageCollector(String messagePrelude) {
            this.combinedMessage = messagePrelude;
        }

        public ExceptionMessageCollector add(Throwable throwable, String rcName, String rcFilename) {
            exceptionsOccurred = true;
            combinedMessage += String.format("\nRanking constant \"%s\" (%s): %s", rcName, rcFilename, throwable.getMessage());
            return this;
        }
    }

    static class TensorValidationFailed extends RuntimeException {
        TensorValidationFailed(String message) {
            super(message);
        }
    }

    @Override
    public void validate(VespaModel model, DeployState deployState) {
        ApplicationPackage applicationPackage = deployState.getApplicationPackage();
        ExceptionMessageCollector exceptionMessageCollector = new ExceptionMessageCollector("Invalid constant tensor file(s):");

        for (SearchDefinition sd : deployState.getSearchDefinitions()) {
            for (RankingConstant rc : sd.getSearch().getRankingConstants().values()) {
                try {
                    validateRankingConstant(rc, applicationPackage);
                } catch (InvalidConstantTensor | FileNotFoundException ex) {
                    exceptionMessageCollector.add(ex, rc.getName(), rc.getFileName());
                }
            }
        }

        if (exceptionMessageCollector.exceptionsOccurred) {
            throw new TensorValidationFailed(exceptionMessageCollector.combinedMessage);
        }
    }

    private void validateRankingConstant(RankingConstant rankingConstant, ApplicationPackage applicationPackage) throws FileNotFoundException {
        ApplicationFile tensorApplicationFile = applicationPackage.getFile(Path.fromString(rankingConstant.getFileName()));
        new ConstantTensorJsonValidator().validate(rankingConstant.getFileName(),
                                                   rankingConstant.getTensorType(),
                                                   tensorApplicationFile.createReader());
    }

}

@@ -284,16 +284,92 @@
 ackage;%0A
+import com.yahoo.config.model.application.provider.FilesApplicationPackage;%0A
 import c
@@ -882,17 +882,16 @@
 ell%0A */%0A
-%0A
 public c
@@ -2693,23 +2693,16 @@
 lication
-Package
 ) throws
@@ -2726,32 +2726,397 @@
 ption %7B%0A        
+String constantFile = rankingConstant.getFileName();%0A        if (application.getFileReference(Path.fromString(%22%22)).getAbsolutePath().endsWith(FilesApplicationPackage.preprocessed) &&%0A            constantFile.startsWith(FilesApplicationPackage.preprocessed))%0A            constantFile = constantFile.substring(FilesApplicationPackage.preprocessed.length());%0A%0A        
 ApplicationFile 
@@ -3150,23 +3150,16 @@
 lication
-Package
 .getFile
@@ -3179,37 +3179,20 @@
 ing(
-rankingC
+c
 onstant
-.get
 File
-Name()
 ));%0A
@@ -3246,37 +3246,20 @@
 ate(
-rankingConstant.getFileName()
+constantFile
 ,%0A  

Handle both .preprocessed and actual root context