1"""
2This module is in charge of taking care of all the information related to
3individual files. Files are identified by the account name and its sid.
4
5
6>>> print(FilesProp.getFileProp('jabberid', '10'))
7None
8>>> fp = FilesProp()
9Traceback (most recent call last):
10    ...
11Exception: this class should not be instatiated
12>>> print(FilesProp.getAllFileProp())
13[]
14>>> fp = FilesProp.getNewFileProp('jabberid', '10')
15>>> fp2 = FilesProp.getFileProp('jabberid', '10')
16>>> fp == fp2
17True
18"""
19
20from typing import Any  # pylint: disable=unused-import
21from typing import ClassVar  # pylint: disable=unused-import
22from typing import Dict  # pylint: disable=unused-import
23from typing import Tuple  # pylint: disable=unused-import
24
25
26class FilesProp:
27    _files_props = {}  # type: ClassVar[Dict[Tuple[str, str], Any]]
28
29    def __init__(self):
30        raise Exception('this class should not be instantiated')
31
32    @classmethod
33    def getNewFileProp(cls, account, sid):
34        fp = FileProp(account, sid)
35        cls.setFileProp(fp, account, sid)
36        return fp
37
38    @classmethod
39    def getFileProp(cls, account, sid):
40        if (account, sid) in cls._files_props.keys():
41            return cls._files_props[account, sid]
42
43    @classmethod
44    def getFilePropByAccount(cls, account):
45        # Returns a list of file_props in one account
46        file_props = []
47        for account_, sid in cls._files_props:
48            if account_ == account:
49                file_props.append(cls._files_props[account, sid])
50        return file_props
51
52    @classmethod
53    def getFilePropByType(cls, type_, sid):
54        # This method should be deleted. Getting fileprop by type and sid is not
55        # unique enough. More than one fileprop might have the same type and sid
56        files_prop = cls.getAllFileProp()
57        for fp in files_prop:
58            if fp.type_ == type_ and fp.sid == sid:
59                return fp
60
61    @classmethod
62    def getFilePropBySid(cls, sid):
63        # This method should be deleted. It is kept to make things compatible
64        # This method should be replaced and instead get the file_props by
65        # account and sid
66        files_prop = cls.getAllFileProp()
67        for fp in files_prop:
68            if fp.sid == sid:
69                return fp
70
71    @classmethod
72    def getFilePropByTransportSid(cls, account, sid):
73        files_prop = cls.getAllFileProp()
74        for fp in files_prop:
75            if fp.account == account and fp.transport_sid == sid:
76                return fp
77
78    @classmethod
79    def getAllFileProp(cls):
80        return list(cls._files_props.values())
81
82    @classmethod
83    def setFileProp(cls, fp, account, sid):
84        cls._files_props[account, sid] = fp
85
86    @classmethod
87    def deleteFileProp(cls, file_prop):
88        files_props = cls._files_props
89        a = s = None
90        for key in files_props:
91            account, sid = key
92            fp = files_props[account, sid]
93            if fp is file_prop:
94                a = account
95                s = sid
96        if a is not None and s is not None:
97            del files_props[a, s]
98
99
100class FileProp:
101
102    def __init__(self, account, sid):
103        # Do not instantiate this class directly. Call FilesProp.getNeFileProp
104        # instead
105        self.streamhosts = []
106        self.transfered_size = []
107        self.started = False
108        self.completed = False
109        self.paused = False
110        self.stalled = False
111        self.connected = False
112        self.stopped = False
113        self.is_a_proxy = False
114        self.proxyhost = None
115        self.proxy_sender = None
116        self.proxy_receiver = None
117        self.streamhost_used = None
118        # method callback called in case of transfer failure
119        self.failure_cb = None
120        # method callback called when disconnecting
121        self.disconnect_cb = None
122        self.continue_cb = None
123        self.sha_str = None
124        # transfer type: 's' for sending and 'r' for receiving
125        self.type_ = None
126        self.error = None
127        # Elapsed time of the file transfer
128        self.elapsed_time = 0
129        self.last_time = None
130        self.received_len = None
131        # full file path
132        self.file_name = None
133        self.name = None
134        self.date = None
135        self.desc = None
136        self.offset = None
137        self.sender = None
138        self.receiver = None
139        self.tt_account = None
140        self.size = None
141        self._sid = sid
142        self.transport_sid = None
143        self.account = account
144        self.mime_type = None
145        self.algo = None
146        self.direction = None
147        self.syn_id = None
148        self.seq = None
149        self.hash_ = None
150        self.fd = None
151        self.startexmpp = None
152        # Type of the session, if it is 'jingle' or 'si'
153        self.session_type = None
154        self.request_id = None
155        self.proxyhosts = None
156        self.dstaddr = None
157
158    def getsid(self):
159        # Getter of the property sid
160        return self._sid
161
162    def setsid(self, value):
163        # The sid value will change
164        # we need to change the in _files_props key as well
165        del FilesProp._files_props[self.account, self._sid]
166        self._sid = value
167        FilesProp._files_props[self.account, self._sid] = self
168
169    sid = property(getsid, setsid)
170
171if __name__ == "__main__":
172    import doctest
173    doctest.testmod()
174