# Copyright 2017 Battelle Energy Alliance, LLC
#
# 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.
"""
  Created on May 17, 2017
  @author: alfoa, wangc
  Module where the base class and the specialization of different type of Model are
"""

#External Modules------------------------------------------------------------------------------------
import copy
import itertools
import numpy as np
import os
#External Modules End--------------------------------------------------------------------------------

#Internal Modules------------------------------------------------------------------------------------
from .Dummy import Dummy
import Decorators
from SupervisedLearning import factory
from utils import utils, xmlUtils, mathUtils
from utils import InputData, InputTypes
from Decorators.Parallelization import Parallel
#Internal Modules End--------------------------------------------------------------------------------

# set enviroment variable to avoid parallelim degradation in some surrogate models
os.environ["MKL_NUM_THREADS"]="1"

class ROM(Dummy):
  """
    ROM stands for Reduced Order Model. All the models here, first learn than predict the outcome
  """
  interfaceFactory = factory
  segmentNameToClass = {'segment': 'Segments',
                 'cluster': 'Clusters',
                 'interpolate': 'Interpolated'}
  @classmethod
  def getInputSpecification(cls, xml=None):
    """
      Method to get a reference to a class that specifies the input data for
      class cls. This one seems a bit excessive, are all of these for this class?
      @ In, cls, the class for which we are retrieving the specification
      @ In, xml, xml.etree.ElementTree.Element, optional, if given then only get specs for
          corresponding subType requested by the node
      @ Out, inputSpecification, InputData.ParameterInput, class to use for
        specifying input of cls.
    """
    inputSpecification = super().getInputSpecification()
    inputSpecification.description = r"""A Reduced Order Model (ROM) is a mathematical model consisting of a fast
                                        solution trained to predict a response of interest of a physical system.
                                        The ``training'' process is performed by sampling the response of a physical
                                        model with respect to variations of its parameters subject, for example, to
                                        probabilistic behavior.
                                        The results (outcomes of the physical model) of the sampling are fed into the