# ============================================================================
# FILE: filename.py
# AUTHOR: <NAME> <Shougo.Matsu at g<EMAIL>>
# License: MIT license
# ============================================================================

from defx.base.column import Base
from defx.context import Context
from defx.util import Nvim

import typing


class Column(Base):

    def __init__(self, vim: Nvim) -> None:
        super().__init__(vim)

        self.name = 'filename'
        self.vars = {
            'indent': ' ',
            'min_width': 40,
            'max_width': 100,
        }

        self._current_length = 0
        self._syntaxes = [
            'directory',
            'hidden',
            'marker',
            'root',
        ]
        self._context: Context = Context()

    def on_init(self, context: Context) -> None:
        self._context = context

    def get(self, context: Context,
            candidate: typing.Dict[str, typing.Any]) -> str:
        return self._truncate(
            self.vars['indent'] * candidate['level'] + candidate['word'])

    def length(self, context: Context) -> int:
        max_fnamewidth = max([self._strwidth(x['word'])
                              for x in context.targets])
        self._current_length = max(
            min(max_fnamewidth, int(self.vars['max_width'])),
            int(self.vars['min_width']))
        return self._current_length

    def syntaxes(self) -> typing.List[str]:
        return [self.syntax_name + '_' + x for x in self._syntaxes]

    def highlight_commands(self) -> typing.List[str]:
        commands: typing.List[str] = []
        commands.append(
            r'syntax match {0}_{1} /\S.*\// contained containedin={0}'.format(
                self.syntax_name, 'directory'))
        commands.append(
            (r'syntax match {0}_{1} /\%{2}c\..*/' +
             ' contained containedin={0}').format(
                 self.syntax_name, 'hidden', self.start))
        root_marker = self.vim.call('escape',
                                    self._context.root_marker, r'~/\.^$[]*')
        commands.append(
            r'syntax match {0}_{1} /{2}/ contained '
            'containedin={0}_root'.format(
                self.syntax_name, 'marker', root_marker))
        commands.append(
            r'syntax match {0}_{1} /{2}.*/ contained '
            'containedin={0}'.format(
                self.syntax_name, 'root', root_marker))
        commands.append(
            'highlight default link {}_{} {}'.format(
                self.syntax_name, 'directory', 'PreProc'))
        commands.append(
            'highlight default link {}_{} {}'.format(
                self.syntax_name, 'hidden', 'Comment'))
        commands.append(
            'highlight default link {}_{} {}'.format(
                self.syntax_name, 'marker', 'Constant'))
        commands.append(
            'highlight default link {}_{} {}'.format(
                self.syntax_name, 'root', 'Identifier'))
        return commands

    def _strwidth(self, word: str) -> int:
        return (int(self.vim.call('strwidth', word))
                if len(word) != len(bytes(word, 'utf-8')) else len(word))

    def _truncate(self, word: str) -> str:
        width = self._strwidth(word)
        if (width > self._current_length or
                len(word) != len(bytes(word, 'utf-8'))):
            return str(self.vim.call(
                'defx#util#truncate_skipping',
                word, self._current_length,
                int(self._current_length / 3), '...'))

        return word + ' ' * (self._current_length - width)
