#   Copyright 2008 Agile42 GmbH, Berlin (Germany)
#   Copyright 2007 Andrea Tomasini <andrea.tomasini_at_agile42.com>
#
#   Licensed under the Apache License, Version 2.0 (the "License");
#   you may not use this file except in compliance with the License.
#   You may obtain a copy of the License at
#
#       http://www.apache.org/licenses/LICENSE-2.0
#
#   Unless required by applicable law or agreed to in writing, software
#   distributed under the License is distributed on an "AS IS" BASIS,
#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#   See the License for the specific language governing permissions and
#   limitations under the License.
#   Author: Andrea Tomasini <andrea.tomasini_at_agile42.com>

from trac.util.translation import _
from agilo.utils.jquery_13_injector import use_jquery_13

# Labels and Titles for Agilo Controls
controls = {
    # Top button bar
    'show':         dict(label=_('自分のチケットを表示'),               title=_('現在のユーザーが所有または割り当てられているチケットを表示')),
    'hide_hide':    dict(label=_('完了済チケットを隠す'),               title=_('完了済チケットを隠す/表示する')),
    'hide_show':    dict(label=_('完了済チケットを表示する'),           title=_('完了済チケットを隠す/表示する')),
    # Sprint Table
    'sprint_cb':    dict(label=_(''),                                   title=_('削除するチケットを選択する')),
    'remaining':    dict(label=_('残存時間'),                           title=_('このタスクの残り時間を入力する')),
    'owner':        dict(label=_('オーナー'),                           title=_('このタスクの所有者を選択する')),
    'resources':    dict(label=_('リソース'),                           title=_('このタスクを作業する他のユーザーをカンマ区切りで入力する')),
    # Backlog Button bar
    'save':         dict(label=_('変更を保存'),                         title=_('このチケットに対する変更を全て保存する')),
    'sort':         dict(label=_('デフォルトソート順'),                 title=_('選択したキーでバックログをソートする (詳細は管理者画面を参照)')),
    # Tickets Button bar
    'delete':       dict(label=_('選択したものを削除'),                 title=_('選択したチケットを完全に削除する')),
    'remove':       dict(label=_('選択したものを除外'),                 title=_('バックログから選択したチケットを削除する(グローバルスコープでない場合)')),
    # Planning Button bar
    'calculate':    dict(label=_('ストーリーポイント/時間を計算する'),  title=_('ユーザーストーリーポイントからバーンダウンチャートを再計算する')),
    'confirm':      dict(label=_('コミットメントの確認'),               title=_('スプリントでのコミットメントを確認する')),
    # Sprint Contingents
    'add':          dict(label=_('追加'),                               title=_('記入した予備時間を追加')),
    'remove_cb':    dict(label=_(''),                                   title=_('削除する予備時間を選択')),
    'contingent':   dict(label=_('予備時間'),                           title=_('予備時間の名前')),
    'amount':       dict(label=_('合計'),                               title=_('予備時間数')),
    'actual':       dict(label=_('実際'),                               title=_('予備時間に時間を追加する')),
    'removesel':    dict(label=_('選択したアイテムを削除'),             title=_('予備時間を削除する')),
    'addtoactual':  dict(label=_('実時間に追加'),                       title=_('予備時間の合計に実時間を追加する')),
    # Product Backlog
    'bv_sel':       dict(label=_('ビジネス価値ポイント'),               title=_('この要求の相対的な価値を選択する')),
    'prio_sel':     dict(label=_('優先度'),                             title=_('この要求の優先度を選択する')),
    'us_sel':       dict(label=_('ユーザーストーリーポイント'),         title=_('このユーザーストーリーの相対的な難易度を選択する')),
    # Roadmap
    'addsprint':    dict(label=_('新しいスプリントを追加'),             title=_('新しいスプリントを追加')),
    'addmilestone': dict(label=_('新しいマイルストーンを追加'),         title=_('新しいマイルストーンを追加')),
}


class Key(object):
    """
    Class grouping all the needed keys to access Ticket properties used
    by Agilo.
    """
    ACTION = 'action'
    ACTUAL_TIME = 'actual_time'
    AGILO_TICKET = 'agilo_ticket'
    ALIAS = 'alias'
    ALTERNATIVE = 'alternative'
    AUTHOR = 'author'
    BUSINESS_VALUE = 'businessvalue'
    CAPACITY = 'capacity'
    CLOSED_TICKETS = 'closed_tickets'
    COLS = 'cols'
    COMMITMENT = 'commitment'
    COMPONENT = 'component'
    CUSTOM = 'custom'
    DATE = 'date'
    DEFAULT_HEIGHT = 'default_height'
    DEFAULT_WIDTH = 'default_width'
    DESCRIPTION = 'description'
    DURATION = 'duration'
    ESTIMATED_REMAINING_TIME = 'estimated_remaining_time'
    ESTIMATED_TIME = 'estimated_time'
    ESTIMATED_VELOCITY = 'estimated_velocity'
    FIELDS = 'fields'
    GLOBAL = 'global'
    HEIGHT = 'height'
    ID = 'id'
    INCOMING_LINKS = 'i_links'
    KEYWORDS = 'keywords'
    LABEL = 'label'
    LEVEL = 'level' # Used in Backlog
    MILESTONE = 'milestone'
    MY_TICKETS = 'my_tickets'
    NAME = 'name'
    OPTIONAL = 'optional'
    OPTIONS = 'options'
    OPTIONS_GROUP = 'optgroups'
    ORDER = 'order'
    OUTGOING_LINKS = 'o_links'
    OWNER = 'owner'
    PANE = 'pane'
    POS = 'pos'
    PRIORITY = 'priority'
    PRODUCT_BACKLOG = 'Product Backlog'
    ROIF = 'roif'
    REMAINING_TIME = 'remaining_time'
    RENDERED = 'rendered'
    REPORTER = 'reporter' # Often used as Stakeholder
    RESOLUTION = 'resolution'
    RESOURCES = 'drp_resources'
    ROWS = 'rows'
    RT_USP_RATIO = 'rt_usp_ratio'
    SCOPE = 'scope'
    SELECT = 'select'
    SKIP = 'skip'
    SPRINT = 'sprint'
    SPRINT_BACKLOG = 'Sprint Backlog'
    START = 'start'
    STATUS = 'status'
    STOP = 'stop'
    STORY_PRIORITY = 'story_priority'
    STORY_POINTS = 'rd_points'
    SUMMARY = 'summary'
    TABLE = 'table'
    TASK_ID = 'task_id'
    TEAM = 'team'
    TICKET = 'ticket'
    TO_POS = 'to_pos'
    TOTAL_REMAINING_TIME = 'total_remaining_time'
    TYPE = 'type'
    # Constant for the use days for time estimations
    USE_DAYS = 'use_days_for_time' 
    VALUE = 'value'
    VELOCITY = 'velocity'
    WIDTH = 'width'


class Type(object):
    """
    Class grouping all the needed types string definition needed for
    Agilo.
    """
    BUG = 'bug'
    IDEA = 'idea'
    IMPEDIMENT = 'impediment'
    REQUIREMENT = 'requirement'
    TASK = 'task'
    USER_STORY = 'story'


class BacklogType(object):    
    GLOBAL = 0     # The Backlog is valid for the whole project database
    SPRINT = 1     # The Backlog requires a Sprint parameter
    MILESTONE = 2  # The Backlog requires a Milestone parameter
    LABELS = { # No unicode here, they can be used as key for a dictionary.
        0 : 'global',
        1 : 'sprint',
        2 : 'milestone',
    }
    
    
class Action(object):
    """Class grouping all actions needed for Agilo"""
    ADD_TIME_FOR_CONTINGENT = 'AGILO_ADD_TIME_FOR_CONTINGENT'
    ATTACHMENT_CREATE = 'ATTACHMENT_CREATE'
    ATTACHMENT_VIEW = 'ATTACHMENT_VIEW'
    BACKLOG_ADMIN = 'AGILO_BACKLOG_ADMIN'
    BACKLOG_EDIT = 'AGILO_BACKLOG_EDIT'
    BACKLOG_VIEW = 'AGILO_BACKLOG_VIEW'
    BROWSER_VIEW = 'BROWSER_VIEW'
    CHANGESET_VIEW = 'CHANGESET_VIEW'
    CREATE_BUG = 'AGILO_CREATE_BUG'
    CREATE_REQUIREMENT = 'AGILO_CREATE_REQUIREMENT'
    CREATE_STORY = 'AGILO_CREATE_STORY'
    CREATE_TASK = 'AGILO_CREATE_TASK'
    DASHBOARD_VIEW = 'AGILO_DASHBOARD_VIEW'
    EMAIL_VIEW = 'EMAIL_VIEW'
    LOG_VIEW = 'LOG_VIEW'
    LINK_EDIT = 'AGILO_LINK_EDIT'
    MILESTONE_CREATE = 'MILESTONE_CREATE'
    MILESTONE_MODIFY = 'MILESTONE_MODIFY'
    MILESTONE_VIEW = 'MILESTONE_VIEW'
    MODIFY_CONTINGENTS = 'AGILO_MODIFY_CONTINGENTS'
    REPORT_VIEW = 'REPORT_VIEW'
    ROADMAP_VIEW = 'ROADMAP_VIEW'
    SAVE_REMAINING_TIME = 'AGILO_SAVE_REMAINING_TIME'
    SEARCH_VIEW = 'SEARCH_VIEW'
    SPRINT_ADMIN = 'AGILO_SPRINT_ADMIN'
    SPRINT_EDIT = 'AGILO_SPRINT_EDIT'
    SPRINT_VIEW = 'AGILO_SPRINT_VIEW'
    TEAM_CAPACITY_EDIT = 'AGILO_TEAM_CAPACITY_EDIT'
    TEAM_VIEW = 'AGILO_TEAM_VIEW'
    TICKET_ADMIN = 'TICKET_ADMIN'
    TICKET_APPEND = 'TICKET_APPEND'
    TICKET_CHANGE = 'TICKET_CHGPROP'
    TICKET_CREATE = 'TICKET_CREATE'
    TICKET_DELETE = 'TICKET_DELETE'
    TICKET_EDIT = 'AGILO_TICKET_EDIT'
    TICKET_EDIT_DESCRIPTION = 'TICKET_EDIT_DESCRIPTION'
    TICKET_EDIT_PAGE_ACCESS = 'AGILO_TICKET_EDIT_PAGE_ACCESS'
    TICKET_MODIFY = 'TICKET_MODIFY'
    TICKET_VIEW = 'TICKET_VIEW'
    TIMELINE_VIEW = 'TIMELINE_VIEW'
    TRAC_ADMIN = 'TRAC_ADMIN'
    WIKI_VIEW = 'WIKI_VIEW'


class Role(object):
    """Constants defining the roles used in Agilo. Aggregates certain actions
    that the Role is allowed to do. The constant name defines the permission
    that a user must have to inhabit this role."""
    BASIC_PERMISSIONS = [
        Action.ATTACHMENT_VIEW,
        Action.BACKLOG_VIEW,
        Action.DASHBOARD_VIEW,
        Action.EMAIL_VIEW,
        Action.MILESTONE_VIEW,
        Action.REPORT_VIEW,
        Action.ROADMAP_VIEW,
        Action.SEARCH_VIEW,
        Action.SPRINT_VIEW,
        Action.TEAM_VIEW,
        Action.TICKET_VIEW,
        Action.TIMELINE_VIEW,
        Action.WIKI_VIEW,
        # Edit permissins
        Action.ATTACHMENT_CREATE,
        Action.TICKET_CREATE, # Needed to create a ticket
        Action.TICKET_CHANGE, # Needed to change any ticket at all
        Action.TICKET_MODIFY, # Needed to be able to change status
        Action.TICKET_APPEND,
        Action.TICKET_EDIT,
        Action.TICKET_EDIT_DESCRIPTION,
    ]
    TICKET_ADMIN = 'TICKET_ADMIN'
    TICKET_ADMIN_ACTIONS = BASIC_PERMISSIONS + [
# fs 2008-09-26:  Don't know why ticket admin gets these permissions again - he
# should have these by the default trac policy. Probably this was because until
# this revision we had own constants for ATTACHMENT_CREATE etc. so TICKET_ADMIN
# did not get these.
#        Action.ATTACHMENT_CREATE,
#        Action.ATTACHMENT_VIEW,
#        Action.TICKET_APPEND,

        # There is no TICKET_EDIT in trac (only more fine-grained permissions)
        # but we check just for TICKET_EDIT so TICKET_ADMIN must get this
        # permission, too
        Action.TICKET_DELETE,
        Action.CREATE_BUG,
        Action.CREATE_REQUIREMENT,
        Action.CREATE_STORY,
        Action.CREATE_TASK,
        Action.LINK_EDIT,
    ]
    PRODUCT_OWNER = 'PRODUCT_OWNER'
    PRODUCT_OWNER_ACTIONS = BASIC_PERMISSIONS + [
        Action.BACKLOG_EDIT,
        Action.CREATE_REQUIREMENT,
        Action.CREATE_STORY,
        Action.SPRINT_EDIT,
        Action.MILESTONE_CREATE,
        Action.MILESTONE_MODIFY
    ]
    SCRUM_MASTER = 'SCRUM_MASTER'
    SCRUM_MASTER_ACTIONS = BASIC_PERMISSIONS + [
        Action.ADD_TIME_FOR_CONTINGENT,
        Action.BACKLOG_EDIT,
        Action.CREATE_TASK,
        Action.MODIFY_CONTINGENTS,
        Action.SAVE_REMAINING_TIME,
        Action.SPRINT_EDIT,
        Action.TEAM_CAPACITY_EDIT,
#        Action.LINK_EDIT,
    ]
    TEAM_MEMBER = 'TEAM_MEMBER'
    TEAM_MEMBER_ACTIONS = BASIC_PERMISSIONS + [
        Action.ADD_TIME_FOR_CONTINGENT,
        Action.CREATE_BUG,
        Action.CREATE_TASK,
        Action.BROWSER_VIEW,
        Action.LOG_VIEW,
    ]


class Status(object):
    """Class to encapsulate the status for a ticket life-cycle"""
    NEW = 'new'
    ACCEPTED = 'accepted'
    ASSIGNED = 'assigned'
    REOPENED = 'reopened'
    CLOSED = 'closed'
    RES_FIXED = 'fixed'
    RES_INVALID = 'invalid'
    RES_WONTFIX = 'wontfix'
    RES_DUPLICATE = 'duplicate'
    RES_WORKSFORME = 'worksforme'


class Realm(object):
    """
    Class to encapsulate all the defined Realms
    """
    TICKET = 'ticket'
    BACKLOG = 'agilo-backlog'
    CONTINGENT = 'agilo-contingent'


# List with ticket mandatory fields
MANDATORY_FIELDS = [
    Key.ID, 
    Key.SUMMARY,
    Key.DESCRIPTION,
    Key.OWNER,
    Key.REPORTER,
    Key.TYPE,
    Key.STATUS,
    Key.RESOLUTION
]

