-- We cannot implement Union like the following (i.e., union of lists) because when two identical RTuples that contain Null values are checked for equality
-- equality comparison between Null returns always false. So we have to implement our own union using the isNull function.

-- | Implements the union of two RTables as a union of two lists (see 'Data.List').
-- Duplicates, and elements of the first list, are removed from the the second list, but if the first list contains duplicates, so will the result
{-runUnion :: 
    RTable
    -> RTable
    -> RTable
runUnion rt1 rt2 = 
    let ls1 = V.toList rt1
        ls2 = V.toList rt2
        resultLs = Data.List.union ls1 ls2
    in  V.fromList resultLs
-}

-- | Implements the union of two RTables as a union of two lists (see 'Data.List').
runUnion :: 
    RTable
    -> RTable
    -> RTable
runUnion rt1 rt2 =
    if isRTabEmpty rt1 && isRTabEmpty rt2
        then 
            emptyRTable
        else
            if isRTabEmpty rt1
                then rt2 
                else
                    if isRTabEmpty rt2
                        then rt1
                        else  
                            -- construct the union result by concatenating the left table with the subset of tuple from the right table that do
                            -- not appear in the left table (i.e, remove dublicates)
                            rt1 V.++ (V.foldr (un) emptyRTable rt2)
                            where
                                un :: RTuple -> RTable -> RTable
                                un tupRight acc = 
                                    -- Can we find tupRight in the left table?            
                                    if didYouFindIt tupRight rt1 
                                        then acc   -- then discard tuplRight ,leave result unchanged          
                                        else V.snoc acc tupRight  -- else insert tupRight into final result



-- | RTable Intersection Operator
runUnion :: 
    RTable
    -> RTable
    -> RTable
runUnion rt1 rt2 =
    if isRTabEmpty rt1 && isRTabEmpty rt2
        then 
            emptyRTable
        else
            if isRTabEmpty rt1
                then rt2 
                else
                    if isRTabEmpty rt2
                        then rt1
                        else  
                            -- construct the union result by concatenating the left table with the subset of tuple from the right table that do
                            -- not appear in the left table (i.e, remove dublicates)
                            rt1 V.++ (V.foldr (un) emptyRTable rt2)
                            where
                                un :: RTuple -> RTable -> RTable
                                un tupRight acc = 
                                    -- Can we find tupRight in the left table?            
                                    if didYouFindIt tupRight rt1 
                                        then acc   -- then discard tuplRight ,leave result unchanged          
                                        else V.snoc acc tupRight  -- else insert tupRight into final result



-- | RTable Intersection Operator
runUnion rt1 rt2 =
    if isRTabEmpty rt1 && isRTabEmpty rt2
        then 
            emptyRTable
        else
            if isRTabEmpty rt1
                then rt2 
                else
                    if isRTabEmpty rt2
                        then rt1
                        else  
                            -- construct the union result by concatenating the left table with the subset of tuple from the right table that do
                            -- not appear in the left table (i.e, remove dublicates)
                            rt1 V.++ (V.foldr (un) emptyRTable rt2)
                            where
                                un :: RTuple -> RTable -> RTable
                                un tupRight acc = 
                                    -- Can we find tupRight in the left table?            
                                    if didYouFindIt tupRight rt1 
                                        then acc   -- then discard tuplRight ,leave result unchanged          
                                        else V.snoc acc tupRight  -- else insert tupRight into final result



-- | RTable Intersection Operator