# indie:lang_version = 5
# Optimized Trend Tracker (OTT) — Indie port
# Original Pine Script by KivancOzbilgic (© KivancOzbilgic)
# License: Mozilla Public License 2.0
# Migration notes:
#   Logic ported 1:1 from the Pine original (stops, dir flip, OTT line shifted by 2 bars, signals)
#   alertcondition() — no Indie equivalent; use platform alerts on lines
#   TSF (linreg) not ported; MA types: SMA/EMA/WMA/TMA/VAR/WWMA/ZLEMA
#   The two Pine fills (long/short highlighter) are merged into one dynamic-color fill

from math import nan, isnan, ceil, floor
from indie import indicator, param, plot, MainContext, color, source, format, MutSeriesF
from indie.algorithms import Sma, Ema, Wma

@indicator('Optimized Trend Tracker', overlay_main_pane=True, format=format.PRICE)
@param.source('src', default=source.CLOSE, title='Source')
@param.int('length', default=2, min=1, title='OTT Period')
@param.float('percent', default=1.4, min=0.0, step=0.1, title='OTT Percent')
@param.bool('showsupport', default=True, title='Show Support Line?')
@param.bool('showsignalsk', default=True, title='Show Support Line Crossing Signals?')
@param.bool('showsignalsc', default=False, title='Show Price/OTT Crossing Signals?')
@param.bool('highlight', default=False, title='Show OTT Color Changes?')
@param.bool('showsignalsr', default=False, title='Show OTT Color Change Signals?')
@param.bool('highlighting', default=True, title='Highlighter On/Off ?')
@param.str('mav', default='VAR', title='MA Type: SMA/EMA/WMA/TMA/VAR/WWMA/ZLEMA')
@plot.line('support', color=color.rgba(5, 133, 225, 1.0), line_width=2, title='Support Line')
@plot.line('ott', color=color.rgba(184, 0, 217, 1.0), line_width=2, title='OTT')
@plot.line('ohlc4_hidden', color=color.TRANSPARENT, line_width=1, title='OHLC4')
@plot.fill('ohlc4_hidden', 'ott', id='trend_fill')
@plot.marker('buy_k', color=color.GREEN, style=plot.marker_style.LABEL)
@plot.marker('sell_k', color=color.RED, style=plot.marker_style.LABEL)
@plot.marker('buy_c', color=color.GREEN, style=plot.marker_style.LABEL)
@plot.marker('sell_c', color=color.RED, style=plot.marker_style.LABEL)
@plot.marker('buy_r', color=color.GREEN, style=plot.marker_style.LABEL)
@plot.marker('sell_r', color=color.RED, style=plot.marker_style.LABEL)
class Main(MainContext):
    def calc(self, src, length, percent, showsupport, showsignalsk, showsignalsc,
             highlight, showsignalsr, highlighting, mav):
        src_val: float = src[0]
        src_prev: float = src[1]

        sma_s = Sma.new(src, length)
        ema_s = Ema.new(src, length)
        wma_s = Wma.new(src, length)
        half: int  = max(1, int(ceil(length / 2.0)))
        half2: int = max(1, int(floor(length / 2.0)) + 1)
        tma1_s = Sma.new(src, half)
        tma_s  = Sma.new(tma1_s, half2)

        # VAR
        valpha: float = 2.0 / (length + 1)
        vud1: float = (src_val - src_prev) if src_val > src_prev else 0.0
        vdd1: float = (src_prev - src_val) if src_val < src_prev else 0.0
        vud_s = MutSeriesF.new(vud1)
        vdd_s = MutSeriesF.new(vdd1)
        vud_sum: float = Sma.new(vud_s, 9)[0] * 9.0
        vdd_sum: float = Sma.new(vdd_s, 9)[0] * 9.0
        vden: float = vud_sum + vdd_sum
        vcmo: float = (vud_sum - vdd_sum) / vden if (not isnan(vden) and vden != 0.0) else 0.0
        var_s = MutSeriesF.new(0.0)
        var_prev: float = var_s[1] if not isnan(var_s[1]) else 0.0
        var_s[0] = valpha * abs(vcmo) * src_val + (1.0 - valpha * abs(vcmo)) * var_prev

        # WWMA
        wwalpha: float = 1.0 / length
        wwma_s = MutSeriesF.new(0.0)
        wwma_prev: float = wwma_s[1] if not isnan(wwma_s[1]) else 0.0
        wwma_s[0] = wwalpha * src_val + (1.0 - wwalpha) * wwma_prev

        # ZLEMA
        zxlag: int = length // 2 if length % 2 == 0 else (length - 1) // 2
        zx_val: float = src_val + (src_val - src[zxlag])
        zx_s = MutSeriesF.new(zx_val)
        zlema_s = Ema.new(zx_s, length)

        mavg: float = var_s[0]
        if mav == 'SMA':
            mavg = sma_s[0]
        elif mav == 'EMA':
            mavg = ema_s[0]
        elif mav == 'WMA':
            mavg = wma_s[0]
        elif mav == 'TMA':
            mavg = tma_s[0]
        elif mav == 'WWMA':
            mavg = wwma_s[0]
        elif mav == 'ZLEMA':
            mavg = zlema_s[0]
        mavg_s = MutSeriesF.new(mavg)
        mavg_prev: float = mavg_s[1]

        fark: float = mavg * percent * 0.01
        long0: float = mavg - fark
        short0: float = mavg + fark
        ls_s = MutSeriesF.new(long0)
        ss_s = MutSeriesF.new(short0)
        long_prev: float = ls_s[1] if not isnan(ls_s[1]) else long0
        short_prev: float = ss_s[1] if not isnan(ss_s[1]) else short0
        ls_s[0] = max(long0, long_prev) if mavg > long_prev else long0
        ss_s[0] = min(short0, short_prev) if mavg < short_prev else short0

        dir_s = MutSeriesF.new(1.0)
        dir_prev: float = dir_s[1] if not isnan(dir_s[1]) else 1.0
        if dir_prev == -1.0 and mavg > short_prev:
            dir_s[0] = 1.0
        elif dir_prev == 1.0 and mavg < long_prev:
            dir_s[0] = -1.0
        else:
            dir_s[0] = dir_prev

        mt: float = ls_s[0] if dir_s[0] == 1.0 else ss_s[0]
        ott: float = (mt * (200.0 + percent) / 200.0) if mavg > mt else (mt * (200.0 - percent) / 200.0)
        ott_s = MutSeriesF.new(ott)
        o2: float = ott_s[2]
        o3: float = ott_s[3]
        o4: float = ott_s[4]

        buy_k: bool  = mavg > o2 and mavg_prev <= o3
        sell_k: bool = mavg < o2 and mavg_prev >= o3
        buy_c: bool  = src_val > o2 and src_prev <= o3
        sell_c: bool = src_val < o2 and src_prev >= o3
        buy_r: bool  = o2 > o3 and o3 <= o4
        sell_r: bool = o2 < o3 and o3 >= o4

        ott_c = (color.GREEN if o2 > o3 else color.RED) if highlight else color.rgba(184, 0, 217, 1.0)
        fill_c = color.TRANSPARENT
        if highlighting:
            if mavg > ott:
                fill_c = color.rgba(0, 128, 0, 0.1)
            elif mavg < ott:
                fill_c = color.rgba(255, 0, 0, 0.1)
        ohlc4: float = (self.open[0] + self.high[0] + self.low[0] + self.close[0]) / 4.0
        ott_plot: float = 0.0 if isnan(o2) else o2

        return (
            plot.Line(mavg if showsupport else nan),
            plot.Line(ott_plot, color=ott_c),
            plot.Line(ohlc4),
            plot.Fill(fill_c),
            plot.Marker(ott * 0.995 if (buy_k and showsignalsk) else nan, text='Buy'),
            plot.Marker(ott * 1.005 if (sell_k and showsignalsk) else nan, text='Sell'),
            plot.Marker(ott * 0.995 if (buy_c and showsignalsc) else nan, text='Buy'),
            plot.Marker(ott * 1.005 if (sell_c and showsignalsc) else nan, text='Sell'),
            plot.Marker(ott * 0.995 if (buy_r and showsignalsr) else nan, text='Buy'),
            plot.Marker(ott * 1.005 if (sell_r and showsignalsr) else nan, text='Sell'),
        )
