module ProjectM36.AttributeNames where
import qualified ProjectM36.Attribute as A
import ProjectM36.Base
import ProjectM36.Error
import qualified Data.Set as S
--AttributeNames is a data structure which can represent inverted projection attributes

empty :: AttributeNames
empty = AttributeNames S.empty

all :: AttributeNames
all = InvertedAttributeNames S.empty

--check that the attribute names are actually in the attributes
projectionAttributesForAttributeNames :: Attributes -> AttributeNames -> Either RelationalError Attributes
projectionAttributesForAttributeNames attrs (AttributeNames attrNameSet) = do
  let nonExistentAttributeNames = A.attributeNamesNotContained attrNameSet (A.attributeNameSet attrs)
  if not $ S.null nonExistentAttributeNames then
    Left $ AttributeNamesMismatchError nonExistentAttributeNames
    else
      return $ A.attributesForNames attrNameSet attrs
projectionAttributesForAttributeNames attrs (InvertedAttributeNames unselectedAttrNameSet) = do
  let nonExistentAttributeNames = A.attributeNamesNotContained unselectedAttrNameSet (A.attributeNameSet attrs)
  if not $ S.null nonExistentAttributeNames then
    Left $ AttributeNamesMismatchError nonExistentAttributeNames
    else
      return $ A.attributesForNames (A.nonMatchingAttributeNameSet unselectedAttrNameSet (A.attributeNameSet attrs)) attrs      
projectionAttributesForAttributeNames attrs (UnionAttributeNames namesA namesB) = do
  attrsA <- projectionAttributesForAttributeNames attrs namesA
  attrsB <- projectionAttributesForAttributeNames attrs namesB
  pure (A.union attrsA attrsB)
projectionAttributesForAttributeNames attrs (IntersectAttributeNames namesA namesB) = A.intersection <$> projectionAttributesForAttributeNames attrs namesA <*> projectionAttributesForAttributeNames attrs namesB  
      
invertAttributeNames :: AttributeNames -> AttributeNames
invertAttributeNames (AttributeNames names) = InvertedAttributeNames names
invertAttributeNames (InvertedAttributeNames names) = AttributeNames names
invertAttributeNames (UnionAttributeNames namesA namesB) = IntersectAttributeNames (invertAttributeNames namesA) (invertAttributeNames namesB)
invertAttributeNames (IntersectAttributeNames namesA namesB) = UnionAttributeNames (invertAttributeNames namesA) (invertAttributeNames namesB)