/// <summary>
        /// Exports currently edited map to binary file
        /// </summary>
        private void ExportMap()
        {
            if (GetViewModel().GameMap == null)
            {
                MessageBox.Show("V editoru není žádná mapa k uložení.", "Chyba", MessageBoxButton.OK, MessageBoxImage.Exclamation);
                return;
            }

            SaveFileDialog saveFileDialog = new SaveFileDialog
            {
                ValidateNames = true,
                Filter        = "Dungeon map file (*.dmap)|*.dmap|All files (*.*)|*.*"
            };

            if (saveFileDialog.ShowDialog() == true)
            {
                string fileName = saveFileDialog.FileName;
                try
                {
                    IMapSerializer <byte[], byte[]> serializer = new BinaryMapSerializer();
                    File.WriteAllBytes(fileName, serializer.Serialize(GetViewModel().GameMap));
                } catch (Exception ex)
                {
                    Utils.ShowErrorMessage($"Chyba při exportu mapy do souboru {fileName}: {ex.Message}.");
                }
            }
        }
        /// <summary>
        /// Imports map from file specified by FileName (property of this model).
        /// Ef error occurs, returns false, otherwise true.
        /// </summary>
        /// <returns>True if map was imported.</returns>
        private bool ImportMapFromFile(string fileName)
        {
            if (fileName == null || !File.Exists(fileName))
            {
                return(false);
            }

            try
            {
                byte[] fileContent;
                fileContent = File.ReadAllBytes(fileName);
                Map deserializedMap = new BinaryMapSerializer().Deserialize(fileContent);
                ImportedMaps.Add(new ImportedMapWrapper()
                {
                    Map = deserializedMap, FilePath = fileName
                });
                return(true);
            } catch (Exception ex)
            {
                return(false);
            }
        }
        /// <summary>
        /// Tries to load map from file to editor.
        /// </summary>
        private void LoadMap()
        {
            OpenFileDialog openFileDialog = new OpenFileDialog
            {
                ValidateNames = true,
                Filter        = "Dungeon map file (*.dmap)|*.dmap|All files (*.*)|*.*"
            };
            string fileName;

            if (openFileDialog.ShowDialog() == true)
            {
                fileName = openFileDialog.FileName;

                // try to load map from file
                Map newMap;
                try
                {
                    byte[] fileContent = File.ReadAllBytes(fileName);
                    newMap = new BinaryMapSerializer().Deserialize(fileContent);
                } catch (Exception ex)
                {
                    Utils.ShowErrorMessage($"Chyba při čtení souboru {fileName}: {ex.Message}. Soubor je poškozený, nebo má neplatný formát.");
                    return;
                }

                // try to load map to editor
                try
                {
                    GetViewModel().LoadMap(newMap);
                    RenderMap();
                } catch (Exception ex)
                {
                    Utils.ShowErrorMessage($"Chyba při načítání mapy do editoru. {ex.Message}");
                    return;
                }
            }
        }
        /// <summary>
        /// Imports map from file specified by FileName (property of this model).
        /// If no FileName is provided or file doesn't exist, exception is thrown.
        /// </summary>
        public void ImportMapFromCurrentFile()
        {
            if (!MapImportEnabled)
            {
                throw new Exception("Není vybrán žádný soubor.");
            }

            if (!File.Exists(FileName))
            {
                throw new Exception($"Soubor {FileName} nebyl nalezen!");
            }

            byte[] fileContent;
            fileContent = File.ReadAllBytes(FileName);
            Map deserializedMap = new BinaryMapSerializer().Deserialize(fileContent);

            ImportedMaps.Add(new ImportedMapWrapper()
            {
                Map = deserializedMap, FilePath = FileName
            });
            FileName = "";

            OnPropertyChanged("ImportedMaps");
        }
        public void TestByteSerialize()
        {
            int w   = 4;
            int h   = 4;
            Map map = MapGeneratorFactory.CreateOpenMapGenerator().GenerateMap(w, h, IMapGeneratorConstants.NO_SEED);

            map.MapName = "";
            IMapSerializer <byte[], byte[]> byteSerializer = new BinaryMapSerializer();

            byte[] serializedMap = byteSerializer.Serialize(map);
            // 3 bytes for header, 20 bytes for map header, (w*h) / 2 bytes for map data, 4 bytes for creature count, 4 bytes for item count
            int expectedSize = 3 + 20 + (w * h) / 2 + 4 + 4;

            Assert.AreEqual(expectedSize, serializedMap.Length, "Wrong number of bytes returned!");

            // check header
            Assert.AreEqual(Convert.ToByte('D'), serializedMap[0], "Wrong first byte of the header!");
            Assert.AreEqual(Convert.ToByte('M'), serializedMap[1], "Wrong second byte of the header!");
            Assert.AreEqual(BinaryMapSerializer.VERSION, serializedMap[2], "Wrong third byte of the header!");

            // check map header
            int counter = 3;
            int nameLen = serializedMap[counter++] + 256 * serializedMap[counter++] + 256 * 256 * serializedMap[counter++] + 256 * 256 * 256 * serializedMap[counter++];
            int sw      = serializedMap[counter++] + 256 * serializedMap[counter++] + 256 * 256 * serializedMap[counter++] + 256 * 256 * 256 * serializedMap[counter++];
            int sh      = serializedMap[counter++] + 256 * serializedMap[counter++] + 256 * 256 * serializedMap[counter++] + 256 * 256 * 256 * serializedMap[counter++];
            int wx      = serializedMap[counter++] + 256 * serializedMap[counter++] + 256 * 256 * serializedMap[counter++] + 256 * 256 * 256 * serializedMap[counter++];
            int wy      = serializedMap[counter++] + 256 * serializedMap[counter++] + 256 * 256 * serializedMap[counter++] + 256 * 256 * 256 * serializedMap[counter++];

            Assert.AreEqual(0, nameLen, "Wrong name length!");
            Assert.AreEqual(w, sw, "Wrong map width!");
            Assert.AreEqual(h, sh, "Wrong map height!");
            Assert.AreEqual(wx, map.WinningBlock.X, "Wrong x coordinate of winning block!");
            Assert.AreEqual(wy, map.WinningBlock.Y, "Wrong y coordinate of winning block!");

            // check map data
            for (int i = counter; i < counter + 8; i++)
            {
                Assert.AreEqual(255, serializedMap[i], $"Wrong {i-18} byte of map data!");
            }

            // check creature and item counts
            Assert.AreEqual(0, serializedMap[33], "Wrong creature count!");
            Assert.AreEqual(0, serializedMap[34], "Wrong item count!");

            // try to deserialize
            Map deserializedMap = byteSerializer.Deserialize(serializedMap);

            // check map
            Assert.AreEqual(map.MapName, deserializedMap.MapName, "Wrong map name!");
            Assert.AreEqual(w, deserializedMap.Width, "Wrong width after deserialization!");
            Assert.AreEqual(h, deserializedMap.Width, "Wrong height after deserialization!");
            Assert.AreEqual(map.WinningBlock.X, deserializedMap.WinningBlock.X, "Wrong x coordinate of winning block!");
            Assert.AreEqual(map.WinningBlock.Y, deserializedMap.WinningBlock.Y, "Wrong Y coordinate of winning block!");

            // check map blocks
            for (int i = 0; i < w; i++)
            {
                for (int j = 0; j < h; j++)
                {
                    MapBlock origBlock   = map.Grid[i, j];
                    MapBlock testedBlock = deserializedMap.Grid[i, j];

                    Assert.IsTrue(testedBlock.North.IsOpen(), $"North entrance of block [{i},{j}] is not open!");
                    Assert.IsTrue(testedBlock.East.IsOpen(), $"East entrance of block [{i},{j}] is not open!");
                    Assert.IsTrue(testedBlock.South.IsOpen(), $"South entrance of block [{i},{j}] is not open!");
                    Assert.IsTrue(testedBlock.West.IsOpen(), $"West entrance of block [{i},{j}] is not open!");
                }
            }
        }
        public void TestSerializeMaze()
        {
            int w   = 4;
            int h   = 4;
            Map map = MapGeneratorFactory.CreateSimpleMapGenerator().GenerateMap(w, h, IMapGeneratorConstants.NO_SEED);

            map.MapName = "Test map";

            // add creatures to map
            Monster origMonster = new Monster("Test monster", map.Grid[0, 0], 4, 3654123, 87621235);

            map.AddCreature(origMonster);
            SimpleAIPlayer aiPlayer = new SimpleAIPlayer("Test player", map.Grid[3, 2]);

            map.AddCreature(aiPlayer);
            HumanPlayer hPlayer = new HumanPlayer("Příliš žluťoučký kůň úpěl ďábelské ódy", map.Grid[1, 3])
            {
                BaseHitPoints = 98432156, BaseAttack = 112348, BaseDeffense = 41226987
            };

            map.AddCreature(hPlayer);

            // add items to map
            AbstractWeapon weapon = ItemFactory.CreateAxe(map.Grid[1, 3]);

            map.AddItem(weapon);
            AbstractArmor armor = ItemFactory.CreateLeatherArmor(map.Grid[1, 1]);

            map.AddItem(armor);
            AbstractInventoryItem item = new BasicItem("Příliš žluťoučký kůň úpěl ďábelské ódy.!?_/()':123456789<>&@{}[]", map.Grid[2, 2], 514)
            {
                UniqueId = 6284
            };

            map.AddItem(item);


            // serialize - deserialize
            IMapSerializer <byte[], byte[]> byteSerializer = new BinaryMapSerializer();

            byte[] serializedMap   = byteSerializer.Serialize(map);
            Map    deserializedMap = byteSerializer.Deserialize(serializedMap);


            // check map
            Assert.AreEqual(map.MapName, deserializedMap.MapName, "Wrong map name!");
            Assert.AreEqual(w, deserializedMap.Width, "Wrong width after deserialization!");
            Assert.AreEqual(h, deserializedMap.Width, "Wrong height after deserialization!");
            Assert.AreEqual(map.WinningBlock.X, deserializedMap.WinningBlock.X, "Wrong x coordinate of winning block!");
            Assert.AreEqual(map.WinningBlock.Y, deserializedMap.WinningBlock.Y, "Wrong Y coordinate of winning block!");


            // check map blocks
            for (int i = 0; i < w; i++)
            {
                for (int j = 0; j < h; j++)
                {
                    MapBlock origBlock   = map.Grid[i, j];
                    MapBlock testedBlock = deserializedMap.Grid[i, j];

                    foreach (Direction dir in  DirectionMethods.GetAllDirections())
                    {
                        Assert.AreEqual(origBlock.EntranceInDirection(dir).IsOpen(), testedBlock.EntranceInDirection(dir).IsOpen(), $"Wrong entrance in direction {dir} in block [{i},{j}].");
                    }
                }
            }


            // check creatures
            Monster m = (Monster)deserializedMap.Grid[0, 0].Creature;

            CheckCreature(origMonster, m);

            SimpleAIPlayer p = (SimpleAIPlayer)deserializedMap.Grid[3, 2].Creature;

            CheckCreature(aiPlayer, p);

            HumanPlayer hp = (HumanPlayer)deserializedMap.Grid[1, 3].Creature;

            CheckCreature(hPlayer, hp);


            // check items
            AbstractWeapon weap = (AbstractWeapon)map.Grid[1, 3].Item;

            CheckItem(weap, weapon);

            AbstractArmor arm = (AbstractArmor)map.Grid[1, 1].Item;

            CheckItem(arm, armor);

            AbstractInventoryItem itm = (AbstractInventoryItem)map.Grid[2, 2].Item;

            CheckItem(item, itm);
        }