# -*- coding: utf-8 -*-
'''
Outputter for displaying results of state runs the most succint way
===================================================================

The tiny outputter has been developed to make the output from shell
commands on minions appear very short but with all the informations
on configuration changes and failures.
'''

# Import python libs
from __future__ import absolute_import
from __future__ import print_function
import logging

# Import salt libs
import salt.utils
from salt.utils.locales import sdecode

# Import 3rd-party libs
import salt.ext.six as six

log = logging.getLogger(__name__)

# Define the module's virtual name
__virtualname__ = 'tiny'

def __virtual__():
    return __virtualname__

class TinyDisplay(object):
    '''
    Create generator for tiyn output
    '''
    def __init__(self):
        self.colors = salt.utils.get_colors(
                __opts__.get('color'),
                __opts__.get('color_theme'))
        self.indent = 2

    def display(self, minion_id, data):
        # Example of data:
        # {
        #   "frghcslsgwv01": {
        #     "file_|-/etc/salt/roster_|-/etc/salt/roster_|-managed": {
        #       "comment": "File /etc/salt/roster is in the correct state",
        #       "pchanges": {},
        #       "name": "/etc/salt/roster",
        #       "start_time": "14:49:50.431497",
        #       "result": true,
        #       "duration": 3.563,
        #       "__run_num__": 4,
        #       "changes": {},
        #       "__id__": "/etc/salt/roster"
        #     },
        #     ...

        minion_id = sdecode(minion_id)

        color = self.colors['CYAN']   # Print the minion name in cyan
        tiny_data = '{0}{1}{2[ENDC]}\n'.format(color, minion_id, self.colors)

        issues = 0
        for block_key in sorted(
                data,
                key=lambda k: data[k].get('__run_num__', 0)):
            ret = data[block_key]

            changes = ret['changes']
            status = ret['result']  # FIXME: status can be None

            if changes:
                color = self.colors['CYAN']
                status_msg = 'ok (changed)'
            elif status:
                color = self.colors['GREEN']
                status_msg = 'ok'
            else:
                color = self.colors['RED']
                status_msg = 'ko'

            if status is False:
                issues += 1

            comps = [sdecode(comp) for comp in block_key.split('_|-')]

            tiny_data += '{0}{1}- ({2}) {3} ... {4}{5[ENDC]}\n'.format(
                         color,
                         ' ' * self.indent,
                         comps[0],
                         comps[2],
                         status_msg,
                         self.colors)

        summary = '{0} '.format(minion_id)
        summary += 'has {0} issue(s)'.format(issues) if issues else \
                   'is in the required state'

        color = self.colors['RED' if issues else 'GREEN']
        tiny_data += '\t{0}-- {1}{2[ENDC]}'.format(color, summary, self.colors)
        return tiny_data

def output(data, **kwargs):  # pylint: disable=unused-argument
    '''
    Print the output data in the most succint way.
    '''
    tiny = TinyDisplay()
    ret = [
        tiny.display(minion_id, minion_data)
            for minion_id, minion_data in six.iteritems(data)
    ]
    if ret:
        return "\n".join(ret)
    log.error(
        'Data passed to ' + __virtualname__ + ' outputter is invalid: %s',
        data
    )
    # We should not reach here, but if we do return empty string
    return ''

@@ -2013,37 +2013,8 @@
 lt'%5D
-  # FIXME: status can be None
 %0A%0A  
@@ -2026,23 +2026,30 @@
      if 
-changes
+status is True
 :%0A      
@@ -2079,19 +2079,20 @@
 colors%5B'
-CYA
+GREE
 N'%5D%0A    
@@ -2123,18 +2123,8 @@
  'ok
- (changed)
 '%0A  
@@ -2137,18 +2137,21 @@
     
-elif statu
+    if change
 s:%0A 
@@ -2157,32 +2157,36 @@
                 
+ 
+   
 color = self.col
@@ -2186,32 +2186,35 @@
 elf.colors%5B'
-GREEN'%5D%0A
+CYAN'%5D%0A    
             
@@ -2220,37 +2220,46 @@
      status_msg 
++
 = '
-ok
+ (changed)
 '%0A            el
@@ -2282,69 +2282,148 @@
     
-color = self.colors%5B'RED'%5D%0A                status_msg = 'ko'%0A
+# status is None when __opts__%5B'test'%5D has been set by user%0A                color = self.colors%5B'LIGHT_YELLOW' if status is None else 'RED'%5D
 %0A   
@@ -2435,27 +2435,33 @@
     
-if
+   
  status
- is False:
+_msg = 'failed'
 %0A   

Support ret['result']=None (test execution mode)