{-# LANGUAGE TemplateHaskell, OverloadedStrings #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}

module HsDev.Tools.AutoFix (
	corrections,
	CorrectorMatch,
	correctors,
	match,
	findCorrector,

	module Data.Text.Region,
	module HsDev.Tools.Refact,
	module HsDev.Tools.Types
	) where

import Control.Applicative
import Control.Lens hiding ((.=), at)
import Data.Maybe (listToMaybe, mapMaybe)
import Data.String (fromString)
import Data.Text (Text)
import Data.Text.Lens (unpacked)
import Data.Text.Region hiding (Region(..), update)
import qualified Data.Text.Region as R

import HsDev.Tools.Refact
import HsDev.Tools.Base
import HsDev.Tools.Types

instance Regioned a => Regioned (Note a) where
	regions = note . regions

corrections :: [Note OutputMessage] -> [Note Refact]
corrections = mapMaybe toRefact where
	toRefact :: Note OutputMessage -> Maybe (Note Refact)
	toRefact n = useSuggestion <|> findCorrector n where
		-- Use existing suggestion
		useSuggestion :: Maybe (Note Refact)
		useSuggestion = do
			sugg <- view (note . messageSuggestion) n
			return $ set
				note
				(Refact
					(view (note . message) n)
					(replace (fromRegion $ view noteRegion n) sugg))
				n

type CorrectorMatch = Note OutputMessage -> Maybe (Note Refact)

correctors :: [CorrectorMatch]
correctors = [
	match "^The (?:qualified )?import of .([\\w\\.]+). is redundant" $ \_ rgn -> Refact -- There are different quotes in Windows/Linux
		"Redundant import"
		(cut
			(expandLines rgn)),
	match "^(.*?)\nFound:\n  (.*?)\nWhy not:\n  (.*?)$" $ \g rgn -> Refact
		(g `at` 1)
		(replace
			((rgn ^. regionFrom) `regionSize` pt 0 (contentsLength $ g `at` 2))
			(g `at` 3))]

match :: String -> ((Int -> Maybe Text) -> R.Region -> Refact) -> CorrectorMatch
match pat f n = do
	g <- matchRx pat (view (note . message . unpacked) n)
	return $ set note (f (fmap fromString . g) (fromRegion $ view noteRegion n)) n

findCorrector :: Note OutputMessage -> Maybe (Note Refact)
findCorrector n = listToMaybe $ mapMaybe ($ n) correctors